任何机会写“ C major”而不是“ major C”

问题描述 投票:4回答:3

我在音乐项目中遇到了一个美学上的小问题,并且困扰了我一段时间。

我具有data Key = C | D | ...类型,可以从ScaleKey构造一个ModeMode区分例如主要和次要规模。

我可以将Mode类型定义为从KeyScale的函数。在这种情况下,模式将使用小写名称(可以),我可以得到一个像这样的Scale

aScale = major C

但是音乐家不会这样说话。他们将此标尺称为C major标尺,而不是major C标尺。

我想要什么

理想情况下我想写

aScale = C major

这有可能吗?

我尝试了什么

我可以使Key成为从Scale构造Mode的函数,所以我可以写

aScale = c Major

但是我不能将关键仅限于构建音阶。其他事物也需要它们(例如,构造chords)。另外Key应该是Show的实例。


当我使用额外的函数(或值构造函数)时,可以将Mode放在Key之后:

[aScale = scale C majorscale :: Key -> Mode -> Scale

但是多余的单词scale看起来很吵,与它的名字相反,scale并不真正关心刻度。智能部分在major中,scale实际上只是flip ($)


使用newtype Mode = Major | Minor ...并没有多大改变,只是scale需要更智能:

aScale = scale C Major

haskell dsl
3个回答
6
投票

[如果您不介意额外的运算符,则可以使用&中的Data.Function。假设major是函数Key -> Scale,则可以编写C & major。产生一个Scale值:

Prelude Data.Function> :t C & major
C & major :: Scale

5
投票

解决方案1:

使用此

data Mode  = Major | Minor
data Scale = C Mode | D Mode | E Mode | F Mode | G Mode | A Mode | B Mode 

现在您可以写(大写字母C和大写字母M)

aScale = C Major

解决方案2a:

这也是可能的

data Mode  = Major | Minor
data Key   = C | D | E | F | G | A | B 

data Scale = Scale Key Mode  

现在您写

aScale = Scale C Major

解决方案2b:

这也是可能的

data Mode  = Major | Minor
data Key   = C | D | E | F | G | A | B 

type Scale = (Key, Mode)  

现在您写

aScale = (C, Major)

2
投票

这是我不真正推荐的一种异想天开的解决方案,但是看起来很“音乐”:

infix 8 ♮
(♮) :: Key -> Mode -> Scale
(♮) = (Data.Function.&)
 -- ≡ flip ($)

然后您可以写

> C♮ major :: Scale

当然,这的真正目的是您还将拥有F♯ minorB♭ major等。

© www.soinside.com 2019 - 2024. All rights reserved.