【发布时间】:2023-03-10 06:42:01
【问题描述】:
我想知道如何写f x = zip x (tail x) in point free。所以我使用了pointfree程序,结果是f = ap zip tail。 ap 是 Control.Monad 中的一个函数
我不明白无点定义是如何工作的。我希望我能从类型的角度理解它。
import Control.Monad (ap)
let f = ap zip tail
let g = ap zip
:info ap zip tail f g
ap :: Monad m => m (a -> b) -> m a -> m b
-- Defined in `Control.Monad'
zip :: [a] -> [b] -> [(a, b)] -- Defined in `GHC.List'
tail :: [a] -> [a] -- Defined in `GHC.List'
f :: [b] -> [(b, b)] -- Defined at <interactive>:3:5
g :: ([a] -> [b]) -> [a] -> [(a, b)]
-- Defined at <interactive>:4:5
通过查看表达式ap zip tail,我认为zip 是ap 的第一个参数,而tail 是ap 的第二个参数。
Monad m => m (a -> b) -> m a -> m b
\--------/ \---/
zip tail
但这是不可能的,因为zip和tail的类型与ap函数所需要的完全不同。即使考虑到列表是某种单子。
【问题讨论】:
-
我唯一能想到的就是ap类型中的
a变成了zip类型的[a] -> [b]。如果是这样,那么一般来说,统一(如果它是正确的词)规则是什么? -
ghci 说类型是
ap zip tail :: Monad ((->) [b]) => [b] -> [(b, b)]... 没有太多调查,我会说Monad ((->) [b])是您想要阅读的内容。我认为 learnyouahaskell.com/for-a-few-monads-more#reader 可能会帮助您了解这里发生了什么。 -
顺便提一下,
zip <*> tail是等效的并且看起来更漂亮 -
@jozefg 对我来说最漂亮的是原始的
f x = zip x (tail x)可能是因为它是唯一能让我立即看到作者意图的形式。