如何将可选属性附加到值? [英] How do I attach optional attributes to values?

查看:93
本文介绍了如何将可选属性附加到值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想存储可以附加一些可选附加属性的事物列表。每件事物都可以有一个或多个属性。不同的属性是不同的类型。



我希望能够在代码中简洁地创建这些事物的文字列表。但是我很难看到如何让类型系统过去,因为元组允许混合类型,但是是固定长度的,而列表是可变长度的,但是是一种类型。



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

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

p>

等。



有什么正确的方法可以做到这一点?

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

  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] =地图Pitch
[55,56,56,57,58,58,59,59,60,61,61,62,63,63,64,64,65,66,66]

类型和弦= [Pitch]

minor:Pitch - > Chord
minor(Pitch fund)=地图(Pitch。(fund +))[0,3,7]

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

spread :: Chord - >和弦
spread =分类
。 zipWith(\ octShift(Pitch note) - > Pitch $ note + 12 * octShift)$ cycle [0,1]

用作例如

 和弦:: [和弦] 
和弦= [小e ,第七d,小e,小a,第七b,差价$小e]

更复杂方法可能实际上以更具有音乐意义的方式存储关于和弦的信息:

 数据Chord = Chord {basic :: Pitch 
,gender ::可能ChordGender
,ExtraNotes :: [AddNote]
,OctaveShifts :: [Int]
}

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

major :: Pitch - >和弦
主要基金=和弦基金(Just Major)[] []

sus4 :: Pitch - > Chord
sus4 fund = Chord fund Nothing [AddNote 4 False] []
$ b $ spread :: Chord - > Chord
spread ch @(Chord _ _ _ shift)
= ch {shifting = cycle [0,1]}

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



如果您不喜欢将属性作为前缀功能,你可以做作为图表包,与

  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
]


I want to store a list of "things" which can have some optional extra attributes attached to them. Each thing can have one or more attributes. And different attributes are of different types.

I want to be able to create literal lists of these things concisely in code. But I'm having trouble seeing how to get this past the type system because tuples allow mixtures of types but are fixed length, while lists are variable length but one type.

This is a toy example of what I want to be able to do :

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

etc.

What's the right way to do this?

解决方案

Basically, rather than storing the attributes as given, you should store the resultant properties of a chord with these attributes. One simple (but not really nice, musically) solution would be, storing only the final pitches:

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]

To be used as e.g.

chords :: [Chord]
chords = [ minor e, seventh d, minor e, minor a, seventh b, spread $ minor e ]

A more sophisticated approach might actually store the information about a chord in a more musically meaningful way:

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

This can be used in much the same way, but is more versatile.

If you don't like giving the attributes as prefix functions, you can do as the diagrams package, with

infixl 8 #
(#) :: a -> (a -> b) -> b
(#) = flip ($)

to write

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

这篇关于如何将可选属性附加到值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆