Có cơ hội nào để viết được C hay không thay vì chính của Cv?


39

Tôi đã gặp một vấn đề thẩm mỹ nhỏ trong dự án âm nhạc của mình và nó đã làm tôi khó chịu một thời gian.

Tôi có một loại data Key = C | D | ...và tôi có thể xây dựng Scaletừ a Keyvà a Mode. Sự Modekhác biệt giữa ví dụ quy mô lớn và quy mô nhỏ.

Tôi có thể định nghĩa Modekiểu là một hàm từ Keyđến Scale. Trong trường hợp đó, các chế độ sẽ có tên chữ thường (không sao) và tôi có thể lấy Tỷ lệ như thế này

aScale = major C

Nhưng các nhạc sĩ không nói như thế này. Họ gọi thang đo này là thang đo C , không phải thang đo C chính .

Những gì tôi muốn

Lý tưởng nhất là tôi muốn viết

aScale = C major

cái này nó có hoàn toàn có thể xảy ra được không?

Những gì tôi đã cố gắng

Tôi có thể tạo Keymột hàm xây dựng Scaletừ a Mode, vì vậy tôi có thể viết

aScale = c Major

Nhưng tôi không thể giới hạn các phím để xây dựng Cân. Chúng cũng cần cho những thứ khác (ví dụ: xây dựng hợp âm ). Cũng Keynên là một ví dụ của Show.


Tôi có thể đặt Modesau Keykhi tôi sử dụng một hàm bổ sung (hoặc hàm tạo giá trị):

aScale = scale C major với scale :: Key -> Mode -> Scale

Nhưng thang đo từ thêm có vẻ ồn ào và trái với tên của nó, scalekhông thực sự quan tâm đến thang đo. Phần thông minh là trong major, scalethực sự chỉ là flip ($).


Sử dụng newtype Mode = Major | Minor ...không thực sự thay đổi nhiều, ngoại trừ scalecần phải thông minh hơn:

aScale = scale C Major

3
Bản thân tôi đã thấy mình muốn cú pháp cực kỳ giống nhau trong quá khứ, nhưng TBH không đáng. Chỉ cần đi với major C.
rẽ trái

4
Cũng giống như một lời ngụy biện về âm nhạc: ngay Key Key là một tên gọi sai cho kiểu dữ liệu đó, vì ví dụ C chính và C phụ là các khóa khác nhau trong thuật ngữ chuẩn. Cận cảnh sân thượng sẽ là một tên chính xác hơn cho các loại.
PLL

2
@PLL Thật vậy, tôi gặp khó khăn khi tìm một cái tên hay cho C, C #, D ... Tôi biết Euterpea sử dụng PitchClass. Nó đúng hơn Key, nhưng không "âm nhạc" chút nào. Ngay bây giờ tôi đang chơi với ý tưởng gọi nó là Root hoặc Tonic mặc dù điều đó chỉ gợi ý Hợp âm và Cân. Cái quái gì mà các nhạc sĩ gọi thứ đó - một ghi chú không có Octave?
Martin Drautzburg

4
@MartinDrautzburg: Tôi sẽ không nói rằng cao độ là phi âm nhạc - nó không chỉ là lập trình viên nói bằng bất kỳ phương tiện nào, nó được thành lập trong lý thuyết âm nhạc có nghĩa là một nốt nhạc mà không có quãng tám kể từ khoảng giữa thế kỷ 20. Nó không phổ biến bên ngoài bối cảnh lý thuyết âm nhạc kỹ thuật, nhưng đó chỉ là do sự khác biệt chính xác giữa một sân bóng và một sân mà không có quãng tám không thực sự cần thiết trong sử dụng hàng ngày, và khi cần, nó thường rõ ràng từ bối cảnh. Tuy nhiên, Root Root hay hay còn gọi là âm thanh tốt, nếu ít chính xác hơn.
PLL

1
Không bởi vì nó không hoạt động ngược lại, một lập trình viên đi vào âm nhạc
Emobe

Câu trả lời:


29

Giải pháp 1:

Dùng cái này

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

Bây giờ bạn có thể viết (với vốn C và vốn M)

aScale = C Major

Giải pháp 2a:

Điều này cũng có thể

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

data Scale = Scale Key Mode  

Bây giờ bạn viết

aScale = Scale C Major

Giải pháp 2b:

Điều này cũng có thể

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

type Scale = (Key, Mode)  

Bây giờ bạn viết

aScale = (C, Major)

IMO đi với giải pháp 2 sẽ phục vụ bạn tốt. Đầu hàng cú pháp của haskell và biến nó thành một mô hình sạch của miền của bạn. Mọi thứ có thể trở nên dễ chịu nếu bạn làm
luqui

16

Đây là một giải pháp hay thay đổi mà tôi không thực sự khuyên dùng, nhưng có vẻ rất hay về nhạc kịch:

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

Sau đó bạn có thể viết

> C major :: Scale

Tất nhiên, nơi mà điều này thực sự được nhắm đến là bạn cũng sẽ có F♯ minorB♭ majorvv ..


1
Tôi tự hỏi nếu có bất cứ thứ gì như không gian không phá vỡ được phép như là một nhà điều hành :)
chepner

26
@chepner thực sự có: U + 2800 BRAille PATTERN BLANK có thể được sử dụng như một phần tử. Không cần phải nói, đây là một ý tưởng khủng khiếp ... Tất cả các ký tự không gian thực tế đều bị cấm dưới dạng infix, nhưng Unicode không có gì đáng ngạc nhiên có chứa thứ gì đó có thể bị hack vào mục đích lạm dụng.
rẽ trái

11

Nếu bạn không phiền một nhà điều hành phụ, bạn có thể sử dụng &từ Data.Function. Giả sử đó majorlà một chức năng Key -> Scale, bạn có thể viết C & major. Điều đó tạo ra một Scalegiá trị:

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

4

Hiện đã có một số câu trả lời hay, nhưng đây là một giải pháp chuyển kiểu tiếp tục có thể hữu ích (có thể không phải cho ví dụ cụ thể này, nhưng trong các bối cảnh khác, nơi cần một loại cú pháp ứng dụng ngược).

Với định nghĩa chuẩn cho một số loại miền có vấn đề:

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)

bạn có thể giới thiệu một loại tiếp tục vượt qua:

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

và viết các kiểu ghi chú nguyên thủy để xây dựng Contcác kiểu như vậy:

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

Sau đó, các hàm xây dựng thang âm, ghi chú và hợp âm có thể phân giải Conts thành các loại đơn giản ở dạng hậu tố (nghĩa là các phần tiếp theo được chuyển đến Cont):

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

note :: Note -> Note
note = id

hoặc dạng tiền tố (nghĩa là lấy Conts làm đối số):

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

Bây giờ, bạn có thể viết:

> 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]

Lưu ý rằng cbản thân nó không có Showví dụ, nhưng c notecó.

Với một sửa đổi cho Noteloại, bạn có thể dễ dàng hỗ trợ các tai nạn kép (ví dụ: c sharp sharpkhác biệt với d), v.v.


Đẹp. Tôi thực sự đã cố gắng giải quyết vấn đề của mình Cont, tuy nhiên, tôi đã cố gắng gắn nó với các nhà xây dựng A | B | C ...thay vì sử dụng các hàm. Tôi không thể làm điều này hoạt động và tôi vẫn không hiểu tại sao, vì các hàm tạo giá trị chỉ là các hàm. Nếu tôi có thể dán một chức năng trước Khóa của mình, nhiều thứ sẽ trở nên khả thi. Nếu chức năng là flip ($)sau đó tôi nhận được mô hình của bạn flip ($) B :: Cont Key r. Bản gốc của tôi aScale = scale C Majorkhông khác nhiều.
Martin Drautzburg

3

Nhưng tôi không thể giới hạn các phím để xây dựng Cân. Chúng cũng cần cho những thứ khác (ví dụ: xây dựng hợp âm). Ngoài ra Key phải là một ví dụ của Show.

Bạn có thể sử dụng máy đánh chữ để xử lý khéo léo xung quanh đó:

{-# 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

Bây giờ, bạn cũng có thể sử dụng các chữ cái viết thường cho các loại khác bằng cách xác định các trường hợp thích hợp.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.