我如何使用我的阅读器:newtype R r a = R {run :: r - >一个 }?

时间:2016-05-31 19:49:32

标签: haskell applicative

我试图通过将类型定义与一些示例相匹配来围绕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 newtype执行上述操作?是你看到的a (r -> a -> b)你从a得到的(r -> a)是一样的,还是我误解了什么?

1 个答案:

答案 0 :(得分:4)

正如我在评论中所说,你基本上拥有你需要的一切 - 缺少的一点就是从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

一旦你有了这个与你的例子相当的调用只涉及从构造函数中包装/解包函数:

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

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

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