มีโอกาสใดบ้างที่จะเขียน“ C major” แทน“ Major C”?


39

ฉันพบปัญหาเกี่ยวกับสุนทรียศาสตร์เล็กน้อยในโครงการดนตรีของฉันและมันก็บั่นทอนฉันมาระยะหนึ่งแล้ว

ฉันมีชนิดdata Key = C | D | ...และฉันสามารถสร้างScaleจากและKey ModeความModeแตกต่างระหว่างเช่นขนาดใหญ่และขนาดเล็ก

ฉันสามารถกำหนดModeประเภทเป็นฟังก์ชั่นจากไปKey Scaleในกรณีนั้นโหมดจะมีชื่อตัวพิมพ์เล็ก (ซึ่งใช้ได้) และฉันสามารถรับสเกลได้เช่นนี้

aScale = major C

แต่นักดนตรีจะไม่พูดเช่นนี้ พวกเขาอ้างถึงขนาดนี้เป็นC ที่สำคัญขนาดไม่c เมเจอร์สเกล

สิ่งที่ฉันต้องการ

เป็นการดีที่ฉันต้องการเขียน

aScale = C major

เป็นไปได้ทั้งหมดหรือไม่

สิ่งที่ฉันพยายาม

ฉันสามารถสร้างKeyฟังก์ชั่นที่สร้างScaleจาก a Modeดังนั้นฉันจึงเขียนได้

aScale = c Major

แต่ฉันไม่สามารถ จำกัด กุญแจในการสร้างเครื่องชั่งได้ พวกเขามีความจำเป็นสำหรับสิ่งอื่น ๆ เช่นกัน (เช่นการสร้างคอร์ด ) นอกจากนี้ควรจะเป็นตัวอย่างของKeyShow


ฉันสามารถใส่ModeหลังKeyเมื่อฉันใช้ฟังก์ชั่นพิเศษ (หรือตัวสร้างมูลค่า):

aScale = scale C major กับ scale :: Key -> Mode -> Scale

แต่ขนาดของคำที่เพิ่มขึ้นนั้นดูเหมือนจะมีเสียงรบกวนและตรงกันข้ามกับชื่อของมันscaleไม่เกี่ยวกับเกล็ด ส่วนที่มีความคิดสร้างสรรค์อยู่ในmajor, เป็นจริงเพียงscaleflip ($)


การใช้ a newtype Mode = Major | Minor ...ไม่ได้เปลี่ยนไปมากนักยกเว้นscaleต้องมีความฉลาดมากขึ้น:

aScale = scale C Major

3
ฉันพบว่าตัวเองต้องการไวยากรณ์ที่คล้ายกันมากในอดีต แต่ TBH มันไม่คุ้มค่า major Cเพียงแค่ไปด้วย
leftaroundabout

4
เช่นเดียวกับการเล่นโวหารดนตรี: "คีย์" เป็นชื่อที่ทำให้เข้าใจผิดสำหรับประเภทข้อมูลนั้นเนื่องจากเช่น C Major และ C minor เป็นคีย์ที่แตกต่างกันในคำศัพท์มาตรฐาน “ PitchClass” จะเป็นชื่อที่แม่นยำกว่าสำหรับประเภทนี้
PLL

2
@PLL จริงฉันมีปัญหาในการหาชื่อที่ดีสำหรับ C, C #, D. .. ฉันรู้ว่า Euterpea ใช้ PitchClass มันถูกต้องมากกว่า Key แต่ไม่ใช่ "Musical" เลย ตอนนี้ฉันกำลังเล่นกับความคิดที่จะเรียกมันว่ารูทหรือโทนิคแม้ว่ามันจะเป็นแค่คอร์ดและสเกลเท่านั้น นักดนตรีทำในสิ่งที่เรียกว่าสิ่งนั้น - โน้ตที่ไม่มีอ็อกเทฟ?
Martin Drautzburg

4
@ มาร์ตินดราทซ์บูร์ก: ฉันจะไม่พูดว่าคลาสพิทช์นั้นไม่ใช่ดนตรี - มันไม่ได้เป็นแค่โปรแกรมเมอร์ที่พูดอะไร แต่มันถูกสร้างขึ้นในทฤษฎีดนตรีที่มีความหมายว่า มันไม่ใช่เรื่องธรรมดานอกบริบททางดนตรีทฤษฎีทางเทคนิค แต่เป็นเพราะความแตกต่างที่แม่นยำระหว่าง "a pitch" และ "a pitch ที่ไม่มี octave" ไม่จำเป็นต้องใช้บ่อยในชีวิตประจำวันและเมื่อจำเป็นก็มักจะชัดเจน จากบริบท แต่เสียง“ รูท” หรือ“ โทนิค” นั้นดีเหมือนคำศัพท์ที่คุ้นเคยเล็กน้อยหากแม่นยำน้อยกว่า
PLL

1
ไม่เพราะมันใช้งานไม่ได้ในทางกลับกันโปรแกรมเมอร์ผู้หนึ่งเข้าสู่ดนตรี
Emobe

คำตอบ:


29

โซลูชันที่ 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)

IMO ไปกับโซลูชันที่ 2 จะให้บริการคุณได้ดี ยอมจำนนต่อ haskell ของไวยากรณ์และทำให้มันเป็นรูปแบบที่สะอาดของโดเมนของคุณ สิ่งที่สามารถทำได้ถ้าคุณทำ
luqui

16

นี่เป็นวิธีแก้ปัญหาแปลก ๆ ที่ฉันไม่แนะนำจริง ๆ แต่มีลักษณะ "ไพเราะ":

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

จากนั้นคุณสามารถเขียน

> C major :: Scale

แน่นอนว่านี่คือเป้าหมายที่แท้จริงคือคุณจะมีF♯ minorและB♭ majorอื่น ๆ อีกมากมาย


1
ฉันสงสัยว่ามีอะไรเช่นพื้นที่ที่ไม่ทำลายที่ได้รับอนุญาตเป็นผู้ดำเนินการ :)
chepner

26
@chepner จริง ๆ แล้วใช่: U + 2800 BRAILLE PATTERN BLANK สามารถใช้เป็นมัดได้ ไม่จำเป็นต้องพูดว่านี่เป็นความคิดที่น่ากลัว ... ตัวละครที่ว่างจริงทั้งหมดถูกห้ามไม่ให้เข้าร่วม แต่ยูนิโค้ดที่แปลกประหลาดมีบางสิ่งที่สามารถแฮ็กเข้าสู่จุดประสงค์การละเมิด
leftaroundabout

11

หากคุณไม่ทราบผู้ประกอบการพิเศษคุณสามารถใช้จาก& Data.Functionสมมติว่าmajorเป็นฟังก์ชั่นKey -> ScaleคุณสามารถเขียนC & majorได้ ที่สร้างScaleมูลค่า:

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

4

มีคำตอบที่ดีอยู่แล้วหลายคำ แต่นี่เป็นวิธีแก้ปัญหาการส่งต่อแบบต่อเนื่องที่อาจเป็นประโยชน์ (อาจไม่ใช่สำหรับตัวอย่างนี้โดยเฉพาะ แต่ในบริบทอื่น ๆ

ด้วยคำจำกัดความมาตรฐานสำหรับปัญหาโดเมนบางประเภท:

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

และเขียนชนิดการสร้างบันทึกย่อดั้งเดิมเพื่อสร้างContประเภทดังนี้:

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

จากนั้นฟังก์ชันการสร้างมาตราส่วนบันทึกย่อและคอร์ดสามารถแก้ไขConts เป็นประเภทธรรมดาในรูปแบบ postfix ทั้ง (เช่นเมื่อดำเนินการต่อเนื่องไปยังCont)

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

note :: Note -> Note
note = id

หรือแบบฟอร์มคำนำหน้า (กล่าวคือการใช้Conts เป็นอาร์กิวเมนต์):

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ตัวเองไม่มีShowอินสแตนซ์ แต่c noteทำ

ด้วยการดัดแปลงเป็นNoteประเภทคุณสามารถรองรับอุบัติเหตุสองครั้งได้อย่างง่ายดาย (เช่นc sharp sharp, แตกต่างจากd) ฯลฯ


ดี จริง ๆ แล้วฉันพยายามแก้ปัญหาด้วยContอย่างไรก็ตามฉันพยายามที่จะยึดมันไว้กับตัวสร้างA | B | C ...แทนที่จะใช้ฟังก์ชั่น ฉันไม่สามารถทำงานนี้ได้ แต่ฉันก็ยังไม่เข้าใจว่าทำไมเนื่องจากตัวสร้างค่าเป็นเพียงฟังก์ชั่น ถ้าฉันสามารถใช้ฟังก์ชั่นด้านหน้าคีย์ของฉันได้หลายสิ่งเป็นไปได้ ถ้าฟังก์ชันคือแล้วฉันจะได้รับรูปแบบของคุณflip ($) flip ($) B :: Cont Key rต้นฉบับของฉันaScale = scale C Majorไม่แตกต่างกันมาก
Martin Drautzburg

3

แต่ฉันไม่สามารถ จำกัด กุญแจในการสร้างเครื่องชั่งได้ พวกเขามีความจำเป็นสำหรับสิ่งอื่น ๆ เช่นกัน (เช่นการสร้างคอร์ด) คีย์ควรเป็นตัวอย่างของการแสดง

คุณสามารถใช้ typeclasses ในการแก้ไข:

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

ตอนนี้คุณสามารถใช้ตัวอักษรพิมพ์เล็กสำหรับประเภทอื่น ๆ ได้ด้วยการกำหนดอินสแตนซ์ที่เหมาะสม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.