如何使Applicative的实例成为某种数据类型

问题描述 投票:1回答:1

[我正在阅读有关Haskell的Graham Hutton的书,并且不要一口气地进行一项练习。练习内容如下:

给出以下类型表达式

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')

最后,我对monad中的>> =有疑问。这个运算符的想法是做诸如替换变量之类的事情?喜欢:

expr >>= (\x -> if x == 'a' then Val 6 else Var x) >>= (\x -> if x == 'b' then Val 7 else Var x)
haskell monads applicative
1个回答
0
投票

[定义了pure(>>=)后,(<*>)的一种可能的定义是

(<*>) = Control.Monad.ap

其中ap在标准库中定义为

ap :: Monad m => m (a -> b) -> m a -> m b
ap mf mx = do
  f <- mf
  x <- mx
  pure (f x)

实际上,(<*>)的任何定义都必须与存在Monad实例的情况相同。

© www.soinside.com 2019 - 2024. All rights reserved.