haskell - Instancing Monoid for a Type -
i have type in haskell make map have several values associated key.
if compile following code:
type mapa k v = map k [v] instance monoid (mapa k v) --mempty :: mapa k v mempty = dm.empty --mappend :: mapa k v -> mapa k v -> mapa k v mappend b = dm.unionwith (++) b
ghci throw:
illegal instance declaration `monoid (map k [v])' (all instance types must of form (t a1 ... an) a1 ... *distinct type variables*, , each type variable appears @ once in instance head. use -xflexibleinstances if want disable this.) in instance declaration `monoid (map k [v])'
should mapa newtype
or data
; or what's problem?
in case, do want create newtype
. when use type
, create type synonym, entirely cosmetic--mapa k v
means same thing map k [v]
. want create new type instead because normal maps have monoid
instance overlap new one, leading confusing behavior.
since mapa
type behaves in fundamentally different way, want different type:
newtype mapa k v = mapa (dm.map k [v])
next, have update instance work on new type. requires 2 changes: have unwrap , rewrap type synonym , have add ord k
constraint. second 1 necessary because keys map have comparable equality and--since map tree internally--they have ordered. new instance this:
instance ord k => monoid (mapa k v) mempty = mapa dm.empty mappend (mapa a) (mapa b) = mapa $ dm.unionwith (++) b
matching against mapa a
lets access underlying map
; can use normal map
functions on it. after you're done, need wrap in mapa
again.
using different type have wrap , unwrap little bit inconvenient, that's price have pay have different instances. makes fact mapa
represents different normal map clearer.
one little style hint can define functions using backticks, infix:
mapa `mappend` mapa b = ...
i think clearer monoids because monoid operation used infix operator.
finally, reason want use newtype
, not data
because newtype
has no runtime overhead: matters typechecker. conceptually, makes sense--you're not creating new type rather using same underlying type in different way different instances.
Comments
Post a Comment