Я читаю книгу Грэма Хаттона о Хаскелле, и не знаю, как выполнить одну часть упражнения. Упражнение говорит следующее:
Учитывая следующие выражения типов
data Expr a = Var a | Val Int | Add (Expr a) (Expr a) deriving Show
, которые содержат переменные некоторого типа a, покажите, как превратить этот тип в экземпляры классов Functor, Applicative и Monad. С помощью примера объясните, что делает оператор >>=
для этого типа.
У меня возникли проблемы с определением оператора <*>
Applicative. Тип <*>
:
(<*>) :: Expr (a -> b) -> Expr a -> Expr b
Я не понимаю, как может работать (Val n) <*> mx
, потому что теоретически мне нужно предоставить Expr b
, но все, что у меня есть, это Expr a
инет функции для преобразования (a -> b
).
Я также не понимаю, что делать в случае (Add l r) <*> mx
.
Это моя реализация.
instance Functor Expr where
--fmap :: (a -> b) -> Expr a -> Expr b
fmap g (Var x) = Var (g x)
fmap g (Val n) = Val n
fmap g (Add l r) = Add (fmap g l) (fmap g r)
instance Applicative Expr where
--pure :: a -> Expr a
pure = Var
-- <*> :: Expr (a -> b) -> Expr a -> Expr b
(Var g) <*> mx = fmap g mx
--(Val n) <*> mx = ???
--(Add l r) <*> mx = ???
instance Monad Expr where
-- (>>=) :: Expr a -> (a -> Expr b) -> Expr b
(Var x) >>= g = g x
(Val n) >>= g = Val n
(Add l r) >>= g = Add (l >>= g) (r >>= g)
expr = Add (Add (Var 'a') (Val 4)) (Var 'b')
Наконец, у меня есть сомнения относительно >> = в монаде. Идея этого оператора заключается в том, чтобы делать такие вещи, как подстановка переменных? Нравится:
expr >>= (\x -> if x == 'a' then Val 6 else Var x) >>= (\x -> if x == 'b' then Val 7 else Var x)