Я изучал моноидов Haskell и их использование , что дало мне довольно хорошее понимание основ моноидов. Одна из вещей, представленных в сообщении блога, - это моноид Any, и его использование выглядит следующим образом:
foldMap (Any . (== 1)) tree
foldMap (All . (> 1)) [1,2,3]
Аналогичным образом я пытался построить моноид Максимума и пришел к следующему:
newtype Maximum a = Maximum { getMaximum :: Maybe a }
deriving (Eq, Ord, Read, Show)
instance Ord a => Monoid (Maximum a) where
mempty = Maximum Nothing
m@(Maximum (Just x)) `mappend` Maximum Nothing = m
Maximum Nothing `mappend` y = y
m@(Maximum (Just x)) `mappend` n@(Maximum (Just y))
| x > y = m
| otherwise = n
Я мог бы довольно легко построить моноид Maximum для определенного типа - скажем, Num, но хочу, чтобы он был полезен для чего угодно (с очевидным требованием, чтобы something являлся экземпляром Ord).
На этом этапе мой код компилируется, но это все. Если я попытаюсь запустить его, я получу следующее:
> foldMap (Just) [1,2,3]
:1:20:
Ambiguous type variable `a' in the constraints:
`Num a' arising from the literal `3' at :1:20
`Monoid a' arising from a use of `foldMap' at :1:0-21
Probable fix: add a type signature that fixes these type variable(s)
Я не уверен, потому что это потому, что я называю его неправильно, или потому что мой моноид неправильный, или и то, и другое. Буду признателен за любые советы о том, где я ' m идет не так (как с точки зрения логических ошибок, так и с точки зрения неидиоматического использования Haskell, поскольку я новичок в этом языке).
- EDIT -
Пол Джонсон в комментарии ниже предложил оставить Maybe вне. Моя первая попытка выглядит так:
newtype Minimum a = Minimum { getMinimum :: a }
deriving (Eq, Ord, Read, Show)
instance Ord a => Monoid (Minimum a) where
mempty = ??
m@(Minimum x) `mappend` n@(Minimum y)
| x < y = m
| otherwise = n
, но я не понимаю, как выразить mempty, не зная, каким должно быть значение mempty. Как я могу это обобщить?