如何使用我的 Reader: newtype R r a = R { 运行 :: r -> a }?

How do I use my Reader: newtype R r a = R { run :: r -> a }?

我试图通过将类型定义与一些示例相匹配来了解 Reader 的应用实例。一个问题是我不知道如何使用我的 Reader newtype。

我对Reader的定义是

newtype R r a =
  R { run :: r -> a }

(<*>) 的类型定义是

(<*>) :: Applicative f => f (a -> b) -> f a -> f b

专用于 Reader 类型,它变为:

(<*>) :: (r -> a -> b) -> (r -> a) -> (r -> b)

所以当我尝试时:

(<*>) (+) (*2) 5 -- seems equivalent to using Reader since the types match

在 REPL 中我得到 15。我想这是因为它计算 (2*5) + 5.

如何使用我的 Reader 新类型执行上述操作?并且是您在中看到的 a (r -> a -> b) 与您从 (r -> a) 得到的 a 相同,还是我误解了什么?

正如我在评论中所说,您基本上拥有所需的一切 - 缺少的只是 wrapping/unwrapping 来自 R 构造函数的函数的技术性。

好的,这是将 R 变成 Applicative 实例的方法:

instance Applicative (R r) where
    pure a          = R (\_ -> a)
    (R f) <*> (R a) = R (\r -> (f r) (a r))

是的,这个:

(<*>) :: (r -> a -> b) -> (r -> a) -> (r -> b)

然后翻译成:

(<*>) :: R r (a -> b) -> R r a -> R r b

一旦你有了这个,相当于你的例子的调用只涉及wrapping/unwrapping来自构造函数的函数:

run (R (+) <*> R (*2)) 5

如果您收到有关 Functor 实例的警告:您也需要这个:

instance Functor (R r) where
    fmap f (R a) = R (\r -> f (a r))