가 발생하는 작은 미적 문제를 내는 음악 프로젝트는 저를 괴롭히는 몇 시간 동안.
나는 형식을 가진데이터의 키=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
해결책 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)
이미 몇 가지 좋은,하지만 여기는'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
)등이 있습니다.
지만 한정 키를 구성하는 것입니다. 그들이 필요한뿐만 아니라 다른 것들에 대한(예:구성하는 코드). 또한 핵심해야의 인스턴스 쇼입니다.
당신이 사용할 수 있는 업스트림 소스를 영위하는:
{-# 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
지금은,사용할 수 있는 소문자에 대한 너무 다른 종류를 정의하여 적절한 인스턴스가 있습니다.