我试图通过将类型定义与一些示例相匹配来围绕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)
是一样的,还是我误解了什么?
答案 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))