11

我想知道如何f x = zip x (tail x)免费写。所以我使用了 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即使考虑到列表是一种单子。

4

2 回答 2

11

所以类型签名apMonad m => m (a -> b) -> m a -> m b. 你已经给出了它ziptail作为参数,所以让我们看看它们的类型签名。

tail :: [a] -> [a] ~ (->) [a] [a](这里~是类型的相等运算符)开始,如果我们将此类型与 的第二个参数的类型进行比较ap

 (->) [x]  [x] ~ m a
((->) [x]) [x] ~ m a

我们得到a ~ [x]m ~ ((->) [x]) ~ ((->) a)。我们已经可以看到我们所在的 monad 是(->) [x],不是[]。如果我们将我们能做的代入到ap我们得到的类型签名中:

(((->) [x]) ([x] -> b)) -> (((->) [x]) [x]) -> (((->) [x]) b)

由于这不是很可读,它更通常可以写成

  ([x] -> ([x] -> b)) -> ([x] -> [x]) -> ([x] -> b)
~ ([x] ->  [x] -> b ) -> ([x] -> [x]) -> ([x] -> b)

的类型zip[x] -> [y] -> [(x, y)]。我们已经可以看到,这与apwhere的第一个参数一致

[x]         ~    [x]   
[y]         ~    [x]   
[(x, y)]    ~    b

在这里,我垂直列出了类型,以便您可以轻松查看哪些类型排列。很明显x ~ x, y ~ x, 和[(x, y)] ~ [(x, x)] ~ b, 所以我们可以完成代b ~ [(x, x)]ap's 类型签名并得到

([x] -> [x] -> [(x, x)]) -> ([x] -> [x]) -> ([x] -> [(x, x)])
--   zip                        tail        ( ap  zip  tail )
--                                            ap  zip  tail u = zip u (tail u)

我希望这能为你解决问题。

编辑:正如danvari 在评论中指出(->) a的那样,monad有时被称为 reader monad。

于 2013-10-04T13:34:06.120 回答
6
于 2015-09-16T02:22:49.717 回答