이 있는 기회를 쓰"C"대신"중요한 C"?

가 발생하는 작은 미적 문제를 내는 음악 프로젝트는 저를 괴롭히는 몇 시간 동안.

나는 형식을 가진데이터의 키=C|D|...하고 작성할 수 있는규모에서는모드. 의모드구별 예:주요 작은 규모입니다.

나는 할 수 있을 정의모드형식 기능으로부터에서규모. 이 경우에는 이 모드는 소문자로 이름(정밀)고 나를 얻을 수 있는 규모이

aScale = major C

하지만 뮤지션 don't 처럼 말이다. 그들은 이러 규모로 C major 규모,아 _major C scale.

내가 무엇을 원하는

이상적으로 I'd 쓰고 싶

aScale = C major

이것이 가능한가요?

내가 무엇을 시도했

내가 만들 수 있는기능이는 구문에규모에서는모드,그래서 내가 쓸 수 있는

aScale = c Major

그러나 나는할 수 없는 제한 키를 구성하는 것입니다. 그들이 필요한뿐만 아니라 다른 것들에 대한(예:구축코드). 또한해야의 인스턴스Show.


넣을 수 있는모드후에내가 사용하는 경우 추가 기능(또는 값을 생성자):

aScale=규모 C 주요가진스케일::키->드->규모

하지만 여분의 단어확장보이는 시끄러운 반하는 그 이름,규모의아't 이 정말로 관심을 가진 것입니다. 지능형 부분에서는,규모정말 그냥플립($).


를 사용하는뉴 Mode=주|보조...지 않't 이 정말로 많이 변화 제외하고,`규모의 요구가 더 지적인:

aScale = scale C Major
질문에 대한 의견 (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)
해설 (1)

여기's 한한 솔루션에는't 이 정말로 추천하지만,매우"음악":

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

다음 작성할 수 있습니다

> C♮ major :: Scale

물론,이것이 정말로 목적은 당신이 또한F♯이너B♭등등....

해설 (2)

지 않는 경우't 마음을 추가,연산자를 사용할 수 있습&에서``데이터입니다.기능. 고 가정하고 있는중요한기능이키->규모을 작성할 수 있습C&a,주요. 을 생성하는규모값:

Prelude Data.Function> :t C & major
C & major :: Scale
해설 (0)

이미 몇 가지 좋은,하지만 여기는's 계속 전달하는 스타일의 솔루션 도움이 될 수있는(아마 이를 위해 특정 예를 들어,하지만 다른 컨텍스트에서는 종류의 역-응용 프로그램의 구문은 원).

과 함께 표준에 대한 정의 몇몇 문제가 도메인 종류:

data Mode = Major | Minor                 deriving (Show)
data Key = C | D | E | F | G | A | B      deriving (Show)
data Semitone = Flat | Natural | Sharp    deriving (Show)

data Note = Note Key Semitone             deriving (Show)
data Scale = Scale Note Mode              deriving (Show)
data Chord = Chord [Note]                 deriving (Show)

할 수 있습을 소개하는 계속 전달하는 유형:

type Cont a r = (a -> r) -> r

고 쓰는 원시적인 참고 건물 형식이 구축하는계속종류는 다음과 같이

a, b, c :: Cont Note r
a = mkNote A
b = mkNote B
c = mkNote C
-- etc.
mkNote a f = f $ Note a Natural

flat, natural, sharp :: Note -> Cont Note r
flat    = mkSemi Flat
natural = mkSemi Natural
sharp   = mkSemi Sharp
mkSemi semi (Note k _) f = f $ Note k semi

그런 다음,규모,참고 및 코드 구축 기능을 해결할 수 있는계속의 일반 유형 중 하나에서 후 양식을(예를 들어,연속 전달되는계속`):

major, minor :: Note -> Scale
major n = Scale n Major
minor n = Scale n Minor

note :: Note -> Note
note = id

또는 접두사 양식을(즉,복 Cont 의 인수로):

chord :: [Cont Note [Note]] -> Chord
chord = Chord . foldr step []
  where step f acc = f (:acc)

이제 작성할 수 있습니다:

> c sharp note
Note C Sharp
> c note
Note C Natural
> c major
Scale (Note C Natural) Major
> b flat note
Note B Flat
> c sharp major
Scale (Note C Sharp) Major
> chord [a sharp, c]
Chord [Note A Sharp,Note C Natural]

참고로c자'tShow인스턴스하지만,c 참고않습니다.

으로 수정을유형,당신은 쉽게 지원이 두 배 임시표(예를 들어,c 날카로운 날카로운,별에서d)등이 있습니다.

해설 (1)

지만 한정 키를 구성하는 것입니다. 그들이 필요한뿐만 아니라 다른 것들에 대한(예:구성하는 코드). 또한 핵심해야의 인스턴스 쇼입니다.

당신이 사용할 수 있는 업스트림 소스를 영위하는:

{-# LANGUAGE FlexibleInstances #-}

data Key = C | D | E | F | G | A | B deriving(Show)

data Mode = Major | Minor

data Scale = Scale Key Mode

class UsesKey t where
  c, d, e, f, g, a, b :: t

instance UsesKey Key where
  c = C
  d = D
  e = E
  f = F
  g = G
  a = A
  b = B

instance UsesKey (Mode -> Scale) where
  c = Scale C
  d = Scale D
  e = Scale E
  f = Scale F
  g = Scale G
  a = Scale A
  b = Scale B

aScale :: Scale
aScale = c Major

지금은,사용할 수 있는 소문자에 대한 너무 다른 종류를 정의하여 적절한 인스턴스가 있습니다.

해설 (0)