理解“第12章”中的应用问题(“7”);在Haskell中编程;

理解“第12章”中的应用问题(“7”);在Haskell中编程;,haskell,functional-programming,applicative,Haskell,Functional Programming,Applicative,我一直在努力完成这项出色的工作。不过,关于应用程序的问题让我有点困惑 鉴于以下类型: data Expr a = Var a | Val Int | Add (Expr a) (Expr a) deriving Show 问题是编写Functor、Applicative和Monad类的实现 Functor很简单,就像Monad一样(至少它可以编译,我还没有完全理解它,但首先我更担心这一点) 我已经提出了这个,可以编译,但我有一些担心: instance Applicative Expr whe

我一直在努力完成这项出色的工作。不过,关于应用程序的问题让我有点困惑

鉴于以下类型:

data Expr a = Var a | Val Int | Add (Expr a) (Expr a) deriving Show
问题是编写
Functor
Applicative
Monad
类的实现

Functor
很简单,就像
Monad
一样(至少它可以编译,我还没有完全理解它,但首先我更担心这一点)

我已经提出了这个,可以编译,但我有一些担心:

instance Applicative Expr where
    -- pure :: a -> Expr a
    pure = Var

    -- (<*>) :: Expr (a -> b) -> Expr a -> Expr b
    (Var fab) <*> fa = fmap fab fa
实例应用程序表达式,其中
--纯::a->Expr a
纯=Var
--()::Expr(a->b)->Expr a->Expr b
(Var fab)fa=fmap fab fa
pure
很好,但我担心实际的应用程序操作符
。据我所知,它只适用于
Var
——而不适用于
Val
Add
。我觉得奇怪的是,你会有一种类型,在这种类型中,表达可以爆炸的东西是合法的-例如,你可以有
Add(Var ord)(Val 10)
,它的类型是
Expr(Char->Int)
,所以在
表达式中,typecheck作为lhs是合法的,但是(就目前而言)会爆炸。我也不清楚递归定义是如何工作的——因为一旦你点击
(Val 10)
,你就被塞住了——没有办法将rhs转换成必要的类型

我错过了什么?如何完成
的定义,使事情不会爆炸,并且它仍然是一个有效的应用程序?我的想法/感觉是对的,在现实中,你不会设计这样的类型吗

谢谢

Val :: Int -> Expr a
对于任何
a
。所以

Val x <*> _ = Val x

您应该使用所有传入的信息生成一个
Expr b
,并保留“结构”(
Add
)。您可以通过哪些方法从中生成
Expr b
(请记住,您可以递归使用applicative操作符)?

如果您已经有
Monad
实例,您只需定义
()=ap
(从
Control.Monad
)。您可以展开定义
ap fab fa
,了解其工作原理。事实上,在这种情况下,定义
fmap
return
join
非常简单直观。然后可以用来构建单子。相比之下,定义应用程序实例感觉就不那么自然了:我只是按照luqui的建议使用
()=ap
,然后忘记它:-p我会学习所有这些东西,所以我只做了
bind
/
=
-我只是模糊地意识到
ap
join
,还没有真正了解它们。我记得有些东西你们可以用其他的东西来定义,反之亦然。希望这本书能更深入地了解它,在完成这本书之后,通过Typeclassopdia将有助于连接这些点。而且,你知道,写一些实际的代码:)尽管,
valxvaly=…
不是真正的选择,是吗?那么
Val x(Add l r)
Val x Var r
呢?正如你所建议的,只有一个正确的答案,正如你在其他地方建议的那样,通过使用
ap
很容易验证。回答得很好,谢谢你帮助我建立我的直觉和理解,而不只是简单地说“这样做”。真的很感激!
_ <*> Val y = Val y
Val x <*> Val y = Val (something about x and y)
Add e e' <*> fb = ...
     -- e :: Expr (a -> b)
     -- e' :: Expr (a -> b)
     -- fb :: Expr a