Wil*_*ess 9
(*>) :: f a -> f b -> f b (<*) :: f a -> f b -> f a
这些类型签名是否真的暗示了上面显示的行为?
当然不是。这两个操作可以简单地实现为
apR :: (Applicative f) => f a -> f b -> f b
apR a b = b
apL :: (Applicative f) => f a -> f b -> f a
apL a b = a
只是忽略Applicative
.f
并且以同样的方式[a] -> Int
并不意味着实现是length
. 它也可以是
foo :: [a] -> Int
foo _ = 42
但是在这两种情况下,这些都不是“正确”的实现,因为推断的类型与给定的签名不同。
那么,您的问题可能有点不同,例如,假设有一个具有匹配推断类型的实现。这是否意味着它做了我们想要做的事情?
答案似乎仍然是否定的。一方面,我们可以定义
apR2 :: (Applicative f) => f a -> f b -> f b
apR2 a b = pure (\a _ b -> b) <*> a <*> b <*> b
对于某些类型,例如您的示例,它不会有所作为。但总的来说,做两次效果与只做一次是不同的。
另一个更有意义的“错误”实现(感谢Daniel Wagner的评论)是
apR2b :: (Applicative f) => f a -> f b -> f b
apR2b a b = pure (\b a -> b) <*> b <*> a
现在,即使您的示例也并不总是有效,因为效果的顺序不同——它首先“做” b
's,在a
's 之前。
更多推荐
暗示,运算符,类型,lt,amp
发布评论