gpt4 book ai didi

haskell - 如何将可选属性附加到值?

转载 作者:行者123 更新时间:2023-12-04 22:05:01 26 4
gpt4 key购买 nike

我想存储一个“事物”列表,这些“事物”可以附加一些可选的额外属性。每个事物都可以有一个或多个属性。并且不同的属性属于不同的类型。

我希望能够在代码中简洁地创建这些内容的文字列表。但是我很难看到如何通过类型系统来解决这个问题,因为元组允许类型的混合但长度是固定的,而列表是可变长度但只有一种类型。

这是我想要做的一个玩具示例:

things = [
Thing 1 RED,
Thing 2 RED LARGE,
Thing 3 BLUE SMALL,
Thing 4 SMALL,
Thing 5 BLUE DOTTED
]

等等。

这样做的正确方法是什么?

最佳答案

基本上,不是存储给定的属性,您应该存储具有这些属性的和弦的结果属性。一个简单的(但不是很好的音乐)解决方案是,只存储最终的音高:

newtype Pitch = Pitch {midiNote :: Int}

a, as, bb, b, bs, c, cs, db, d, ds, eb, e, es, f, fs, gb, g, gs, ab :: Pitch
[ a, as,bb, b,bs, c,cs,db, d,ds,eb, e,es, f,fs,gb, g,gs,ab] = map Pitch
[55,56,56,57,58,58,59,59,60,61,61,62,63,63,64,64,65,66,66]

type Chord = [Pitch]

minor :: Pitch -> Chord
minor (Pitch fund) = map (Pitch . (fund+)) [0, 3, 7]

seventh :: Pitch -> Chord
seventh (Pitch fund) = map (Pitch . (fund+)) [0, 4, 7, 10]

spread :: Chord -> Chord
spread = sort
. zipWith (\octShift (Pitch note) -> Pitch $ note + 12 * octShift) $ cycle [0,1]

用作例如
chords :: [Chord]
chords = [ minor e, seventh d, minor e, minor a, seventh b, spread $ minor e ]

更复杂的方法实际上可能以更有意义的方式存储有关和弦的信息:
data Chord = Chord { fundamental :: Pitch
, gender :: Maybe ChordGender
, ExtraNotes :: [AddNote]
, OctaveShifts :: [Int]
}

data ChordGender = Major | Minor
data AddNote = AddNote { roughInterval :: Int, intervalIsMajor :: Bool }

major :: Pitch -> Chord
major fund = Chord fund (Just Major) [] []

sus4 :: Pitch -> Chord
sus4 fund = Chord fund Nothing [AddNote 4 False] []

spread :: Chord -> Chord
spread ch@(Chord _ _ _ shifts)
= ch{shifts = cycle [0,1]}

这可以以几乎相同的方式使用,但更通用。

如果你不喜欢把属性作为前缀函数,你可以做 as the diagrams package, with
infixl 8 #
(#) :: a -> (a -> b) -> b
(#) = flip ($)

来写
chords = [ c # major
, g # sus4
, g # major
, a # minor
, f # major # spread
, g # sus4 # spread
, g # major # spread
, c # major # spread
]

关于haskell - 如何将可选属性附加到值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22133995/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com