Проблема, с которой я столкнулся, связана с приложением >>=
к типу образца, подобному этому:
data ThreeArgs a = ThreeArgs a a a deriving (Show,Eq)
instance Functor ThreeArgs where
fmap f (ThreeArgs a b c) = ThreeArgs (f a) (f b) (f c)
instance Applicative ThreeArgs where
pure x = ThreeArgs x x x
(ThreeArgs a b c) <*> (ThreeArgs p s q) = ThreeArgs (a p) (b s) (c q)
Я бы объявил экземпляр Monad следующим образом:
instance Monad ThreeArgs where
return x = ThreeArgs x x x
(ThreeArgs a b c) >>= f = f ... -- a code I need to complete
Да, похоже, что f
применяется ко всем трем аргументам ThreeArgs
. Если я завершу последнюю строку
(ThreeArgs a b c) >>= f = f a
, то компилятор не будет иметь никаких претензий, тогда как результат:
*module1> let x = do { x <- ThreeArgs 1 2 3; y <- ThreeArgs 4 6 7; return $ x + y }
*module1> x
ThreeArgs 5 5 5
это означает, что суммирование приводит к контексту с теми же значениями аргумента, хотя правильный вывод должен быть ThreeArgs 5 8 10
. Как только я отредактировал в
(ThreeArgs a b c) >>= f = (f a) (f b) (f c)
предупреждения компилятора:
Couldn't match expected type `ThreeArgs b
-> ThreeArgs b -> ThreeArgs b -> ThreeArgs b'
with actual type `ThreeArgs b'
Итак, я вижу серьезную ошибку, направляющую мое понимание, но мне все еще довольно трудно понять класс monadi c и еще такие вещи в Haskell. Предположительно, я хочу использовать рекурсию здесь или что еще?