क्या "प्रमुख सी" के बजाय "सी प्रमुख" लिखने का कोई मौका है?


39

मुझे अपने संगीत प्रोजेक्ट में एक छोटे से सौंदर्य मुद्दे का सामना करना पड़ा और यह मुझे कुछ समय के लिए परेशान कर रहा है।

मेरे पास एक प्रकार है data Key = C | D | ...और मैं ScaleKeyऔर ए से निर्माण कर सकता हूं ModeModeएक प्रमुख और एक छोटे पैमाने पर जैसे के बीच का अंतर।

मैं परिभाषित कर सकते हैं Modeसे एक समारोह के रूप प्रकार Keyके लिए Scale। उस स्थिति में मोड में लोअरकेस नाम होंगे (जो ठीक है) और मुझे इस तरह स्केल मिल सकता है

aScale = major C

लेकिन संगीतकार इस तरह की बात नहीं करते। वे इस पैमाने को C प्रमुख पैमाने के रूप में संदर्भित करते हैं , प्रमुख C स्केल को नहीं।

मैं क्या चाहता हूँ

आदर्श रूप में मैं लिखना चाहूंगा

aScale = C major

क्या यह वास्तव में संभव है?

मैंने क्या कोशिश की

मैं Keyएक ऐसा फंक्शन बना सकता हूं, जो ए Scaleसे बनता है Mode, इसलिए मैं लिख सकता हूं

aScale = c Major

लेकिन मैं तराजू के निर्माण के लिए कुंजी को सीमित नहीं कर सकता। वे अन्य चीजों के लिए भी आवश्यक हैं (जैसे कि chords का निर्माण )। का Keyएक उदाहरण भी होना चाहिए Show


जब मैं एक अतिरिक्त फ़ंक्शन (या मूल्य निर्माणकर्ता) का उपयोग करता हूं Mode, Keyतो मैं इसे डाल सकता हूं :

aScale = scale C major साथ में scale :: Key -> Mode -> Scale

लेकिन अतिरिक्त शब्द पैमाने शोर और इसके नाम के विपरीत दिखता है, scaleवास्तव में तराजू से चिंतित नहीं है। बुद्धिमान हिस्सा है major, scaleवास्तव में बस है flip ($)


newtype Mode = Major | Minor ...वास्तव में बहुत अधिक परिवर्तन scaleकरने की आवश्यकता नहीं है, सिवाय इसके कि अधिक बुद्धिमान होने का उपयोग न करें :

aScale = scale C Major

3
मैंने खुद को अतीत में बेहद समान वाक्य विन्यास चाहा है, लेकिन टीबीएच इसके लायक नहीं है। बस साथ चलते हैं major C
लेफ्टरनबाउट

4
म्यूजिकल क्विबल के रूप में: "की" उस डेटाटाइप के लिए एक भ्रामक नाम है, जैसे कि सी प्रमुख और सी नाबालिग मानक शब्दावली में अलग-अलग कुंजी हैं। "पिचक्लास" प्रकार के लिए एक अधिक सटीक नाम होगा।
पीएलएल

2
@ एलपीएल वास्तव में, मुझे C, C #, D ... के लिए एक अच्छा नाम खोजने में परेशानी हो रही है ... मुझे पता है कि Euterpea PitchClass का उपयोग करता है। यह कुंजी की तुलना में अधिक सही है, लेकिन "संगीतमय" बिल्कुल नहीं। अभी मैं इसे रूट या टॉनिक कहने के विचार से खेल रहा हूं, हालांकि यह केवल Chords और Scales का सुझाव देता है। संगीतकार उस चीज़ को क्या कहते हैं - एक नोट बिना ऑक्टेव के?
मार्टिन ड्रुट्ज़बर्ग

4
@MartinDrautzburg: मैं यह नहीं कहूंगा कि पिच क्लास अन-म्यूजिकल है - यह किसी भी तरह से केवल प्रोग्रामर-स्पीक नहीं है, यह कम से कम 20 वीं शताब्दी के मध्य के बाद से अर्थ "एक नोट बिना ऑक्टेव" के रूप में संगीत सिद्धांत में स्थापित किया गया है। यह आमतौर पर तकनीकी संगीत-सिद्धांत के संदर्भों के बाहर नहीं है, लेकिन ऐसा सिर्फ इसलिए है क्योंकि "एक पिच" ​​और "एक ओक्टेव के बिना एक पिच" ​​के बीच सटीक अंतर वास्तव में रोजमर्रा के उपयोग में अक्सर आवश्यक नहीं होता है, और जब इसकी आवश्यकता होती है, तो यह आमतौर पर स्पष्ट होता है संदर्भ से। लेकिन "रूट" या "टॉनिक" कम सटीक होने पर थोड़ा अधिक परिचित शब्दों के रूप में ठीक लगता है।
पीएलएल

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

समाधान 2 बी:

यह भी संभव है

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

type Scale = (Key, Mode)  

अब आप लिखिए

aScale = (C, Major)

समाधान 2 के साथ जाने वाला IMO आपकी अच्छी सेवा करेगा। हैकेल के सिंटैक्स को आत्मसमर्पण करें और इसे अपने डोमेन का एक साफ मॉडल बनाएं। हालात सुखद यदि आप ऐसा करते हैं किया जा सकता है
luqui

16

यहाँ एक सनकी समाधान है जिसकी मैं वास्तव में सिफारिश नहीं करता, लेकिन बहुत "संगीतमय" दिखता है:

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

फिर आप लिख सकते हैं

> C major :: Scale

बेशक, जहां यह वास्तव में उद्देश्य है कि आपके पास भी होगा F♯ minorऔरB♭ major आदि।


1
मुझे आश्चर्य है कि अगर गैर-ब्रेकिंग स्पेस जैसी कोई चीज है जिसे ऑपरेटर के रूप में अनुमति दी गई है :)
chepner

26
@chepner वास्तव में हाँ: U + 2800 BRAVLE PATTERN BLANK का उपयोग इन्फिक्स के रूप में किया जा सकता है। कहने की जरूरत नहीं है, यह एक भयानक विचार है ... सभी वास्तविक अंतरिक्ष पात्रों को इन्फिक्स के रूप में मना किया जाता है, लेकिन अनिश्चित रूप से यूनिकोड में कुछ ऐसा होता है जिसे दुरुपयोग के उद्देश्य से हैक किया जा सकता है।
वामावर्तबौट

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

फिर, स्केल, नोट, और कॉर्ड बिल्डिंग फ़ंक्शन Contएस को सादे प्रकारों में या तो पोस्टफिक्स फॉर्म में हल कर सकते हैं (यानी, जैसा कि जारी रखा जाएगा Cont):

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अपने आप में एक Showउदाहरण नहीं है , लेकिनc note करता है।

Noteप्रकार में संशोधन के साथ , आप आसानी से दोहरे दुर्घटना (जैसे, c sharp sharpसे अलग d), आदि का समर्थन कर सकते हैं ।


अच्छा लगा। मैंने वास्तव में अपनी समस्या को हल करने की कोशिश की थी Cont, लेकिन मैंने A | B | C ...कार्यों का उपयोग करने के बजाय इसे निर्माणकर्ताओं से चिपकाने की कोशिश की । मुझे यह काम करने के लिए नहीं मिला और मुझे अभी भी समझ में नहीं आया है, यह देखते हुए कि मूल्य निर्माता केवल कार्य हैं। अगर मैं अपनी कीज़ के सामने फंक्शन चिपका सकता हूं, तो कई चीजें संभव हो सकती हैं। अगर फंक्शन है flip ($)तो मुझे आपका पैटर्न मिलेगा flip ($) B :: Cont Key r। मेरा मूल aScale = scale C Majorज्यादा अलग नहीं है।
मार्टिन ड्रुटज़बर्ग

3

लेकिन मैं तराजू के निर्माण के लिए कुंजी को सीमित नहीं कर सकता। वे अन्य चीजों के लिए भी आवश्यक हैं (जैसे कि chords का निर्माण)। इसके अलावा की को शो का एक उदाहरण होना चाहिए।

आप इसके आसपास चतुराई से काम करने के लिए टाइपकास्टेस का उपयोग कर सकते हैं:

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

अब, आप अन्य प्रकारों के लिए लोअरकेस अक्षरों का उपयोग भी उपयुक्त उदाहरणों को परिभाषित करके कर सकते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.