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

Jor*_*rdi 3 monads haskell applicative

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

给定以下类型表达式

data Expr a = Var a | Val Int | Add (Expr a) (Expr a) deriving Show
Run Code Online (Sandbox Code Playgroud)

包含某些类型a的变量,展示了如何使这种类型成为Functor,Applicative和Monad类的实例。借助示例,说明>>=该类型的运算符的作用。


我在定义<*>Applicative运算符时遇到了问题。的类型<*>是:

(<*>) :: Expr (a -> b) -> Expr a -> Expr b
Run Code Online (Sandbox Code Playgroud)

我不知道该怎么用(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')
Run Code Online (Sandbox Code Playgroud)

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

expr >>= (\x -> if x == 'a' then Val 6 else Var x) >>= (\x -> if x == 'b' then Val 7 else Var x)
Run Code Online (Sandbox Code Playgroud)

K. *_*uhr 5

如您所正确指出的,在这种情况下:

(Val n) <*> mx = ???
Run Code Online (Sandbox Code Playgroud)

你有:

Val n :: Expr (a -> b)
mx :: Expr a
Run Code Online (Sandbox Code Playgroud)

并且您需要产生一个Expr b。您是否记得这种情况:

fmap g (Val n) = ???
Run Code Online (Sandbox Code Playgroud)

当你有:

g :: a -> b
Val n :: Expr a
Run Code Online (Sandbox Code Playgroud)

而您需要产生一个Expr b?您在那里找到了解决方案。

对于这种情况:

(Add l r) <*> mx
Run Code Online (Sandbox Code Playgroud)

你有:

l :: Expr (a -> b)
r :: Expr (a -> b)
mx :: Expr a
Run Code Online (Sandbox Code Playgroud)

并且您需要产生一个Expr b。如果只有你有一些功能,可以采取lmx创造的Expr b。这样的功能(如果存在)可能具有签名:

someFunc :: Expr (a -> b) -> Expr a -> Expr b
Run Code Online (Sandbox Code Playgroud)

当然,如果同时使用someFunc l mx和和someFunc r mx,都使用type Expr b,那只能使用一个是可耻的。如果有一些方法构建一个Expr b由两个Expr b部分,即真的会蜜蜂的膝盖。