Emr*_*inç 8 haskell applicative
我坚持在Haskell Book中练习,"第22章读者".练习说"实施阅读器的应用",它给出了以下内容:
{-# LANGUAGE InstanceSigs #-}
newtype Reader r a =
Reader { runReader :: r -> a }
instance Applicative (Reader r) where
pure :: a -> Reader r a
pure a = Reader $ ???
(<*>) :: Reader r (a -> b) -> Reader r a -> Reader r b
(Reader rab) <*> (Reader ra) = Reader $ \r -> ???
Run Code Online (Sandbox Code Playgroud)
我pure之后也写了一个Functor实例(我编写了Functor实例,因为否则GHC抱怨"没有(Functor (Reader r)) …实例声明的超类引起的实例在实例声明中为‘Applicative (Reader r)’"):
{-# LANGUAGE InstanceSigs #-}
newtype Reader r a =
Reader { runReader :: r -> a }
instance Functor (Reader r) where
fmap f (Reader x) = Reader (f . x)
instance Applicative (Reader r) where
pure :: a -> Reader r a
pure a = Reader $ \_ -> a
(<*>) :: Reader r (a -> b) -> Reader r a -> Reader r b
(Reader rab) <*> (Reader ra) = Reader $ \r -> ???
Run Code Online (Sandbox Code Playgroud)
但我坚持这???部分.
该书给出了以下提示:
我们为您启动了apply函数的定义,我们将描述您需要做什么并编写代码.如果您打开上面适用的Reader类型,您将获得以下内容.
Run Code Online (Sandbox Code Playgroud)<*> :: (r -> a -> b) -> (r -> a) -> (r -> b) -- contrast this with the type of fmap fmap :: (a -> b) -> (r -> a) -> (r -> b)那有什么区别?不同之处在于
apply,它fmap也采用了类型的论证r.这样做.
是的,但如何做到这一点?使用类型化的孔,编译器告诉我???必须是类型b.但我仍然无法看到如何构造一个lambda表达式,它接受一个r类型b,给定rab和返回的东西ra.
Ben*_*son 11
看看你在范围内的作品,
rab :: r -> (a -> b)
ra :: r -> a
r :: r
Run Code Online (Sandbox Code Playgroud)
和你的目标类型b,你可以看到你可以b通过应用rab两个参数的唯一方法.
Reader rab <*> Reader ra = Reader $ \r -> rab _ _
Run Code Online (Sandbox Code Playgroud)
现在,第一个洞有一个类型r,你只有一个r在范围内.
Reader rab <*> Reader ra = Reader $ \r -> rab r _
Run Code Online (Sandbox Code Playgroud)
剩下的洞有一种类型a.a你在范围内唯一的是返回值ra,
Reader rab <*> Reader ra = Reader $ \r -> rab r (ra _)
Run Code Online (Sandbox Code Playgroud)
而且ra这个论点必须是一个r,你再一次只有一个选择.
Reader rab <*> Reader ra = Reader $ \r -> rab r (ra r)
Run Code Online (Sandbox Code Playgroud)
请注意,rab并且ra都r作为参数接收.组合Reader计算中的所有步骤都可以访问相同的环境.
顺便提一下,这个定义<*>相当于着名的S组合子(并且pure是K).