I'm not sure how to write the semigroup instance for this map newtype:
import Data.Map (Map)
import qualified Data.Map as Map
newtype mymap = MyMap (Map Int String)
instance Semigroup (MyMap k v) where
MyMap a <> MyMap b = Map.compose a b
error:
• Expected kind ‘k -> k1 -> *’, but ‘MyMap’ has kind ‘*’
• In the first argument of ‘Semigroup’, namely ‘(MyMap k v)’
In the instance declaration for ‘Semigroup (MyMap k v)’
|
6 | instance Semigroup (MyMap k v) where
| ^^^^^^^^^
I thought that MyMap (Map Int String) would have kind * -> * -> * as it takes two types (Int and String) and returns a mymap type
Thanks!
You should write your datatype capitalized
Type
MyMaphas no arguments, notice that I renamed the constructorMkMyMapto disambiguate between them:Map.composewill not work as a semigroup operation unless the map has typeMap A A:Let's see what happens when the first argument is
Map Int String:If we are returning
Map Int Stringas well, it forces the second argument to beMap Int IntThere is a template for how maps can be defined, using a Monoid to accumulate conflicts: MonoidalMap key a.
This unions the two Maps using the
Semigroup Stringfor the value of every duplicate key. If we used a different Semigroup instanceSemigroup.First Stringthen the first key is chosen:and the last key is chosen if we use
Semigroup.Last String.There are also other combinations, some of which are rather strange. For example using Applicative lifting (
Ap):