【问题标题】:How to write the <*> when writing the Applicative instance for Reader r为 Reader r 编写 Applicative 实例时如何编写 <*>
【发布时间】:2023-03-24 07:01:01
【问题描述】:

我在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 -> ???

在编写Functor 实例之后,我能够编写pure(我编写了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 -> ???

但我坚持使用 ??? 部分。

这本书给出了以下提示:

我们已经为您定义了 apply 函数,我们将 描述你需要做什么,然后编写代码。如果你打开包装 上面的读者申请类型,你得到以下。

<*> :: (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。但是我仍然看不到如何构造一个接受r 并返回b 类型的lambda 表达式,给定rabra

【问题讨论】:

  • 您能否也为我们这些不打算购买那本书的人提供Reader 数据类型的定义?
  • @Rhymoid 这有点苛刻。毕竟Reader是常识。
  • 抱歉,缺少 Reader 类型,我已将其添加到上述问题中。

标签: haskell applicative


【解决方案1】:

让我们打网球吧。查看范围内的部分,

rab :: r -> (a -> b)
ra :: r -> a
r :: r

以及b 的目标类型,您可以看到获得b 的唯一方法是将rab 应用于两个参数。

Reader rab <*> Reader ra = Reader $ \r -> rab _ _

现在,第一个洞的类型为 r,而您的范围内只有一个 r

Reader rab <*> Reader ra = Reader $ \r -> rab r _

剩余孔的类型为a。范围内唯一的ara 的返回值,

Reader rab <*> Reader ra = Reader $ \r -> rab r (ra _)

并且ra 的参数必须是r,对此您再次只有一个选择。

Reader rab <*> Reader ra = Reader $ \r -> rab r (ra r)

注意rabra 都接收r 作为参数。组合Reader 计算中的所有步骤都可以访问相同的环境。

顺便说一句,这个定义使&lt;*&gt; 等同于著名的S combinator(而pureK)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-19
    • 1970-01-01
    • 2019-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-26
    • 1970-01-01
    相关资源
    最近更新 更多