表达式“ap zip tail”是如何工作的 [英] How does the expression `ap zip tail` work

查看:194
本文介绍了表达式“ap zip tail”是如何工作的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道如何在免费的地方写 f x = zip x(tail x)。所以我使用了pointfree程序,结果是 f = ap zip tail ap 是Control.Monad的一个函数



我不明白point free定义是如何工作的。我希望能够从类型的角度理解它。

b $ b let f = ap zip tail
let g = ap zip
:info ap zip tail fg
ap :: Monad m => m(a - > b) - > m a - > m b
- 在`Control.Monad'中定义
zip :: [a] - > [b] - > [(a,b)] - 在`GHC.List'中定义
tail :: [a] - > [a] - 在`GHC.List'中定义
f :: [b] - > [(b,b)] - 定义于< interactive>:3:5
g ::([a] - > [b]) - > [a] - > [(a,b)]
- 定义于< interactive>:4:5



<通过查看表达式 ap zip tail 我会认为zip是 ap 的第一个参数,tail是第二个参数 ap

  Monad m => m(a  - > b) - > m a  - > mb 
\ -------- / \ --- /
zip tail

但是这是不可能的,因为 zip tail 的类型完全不同于函数 ap 需要什么。即使考虑到这个列表是一个monad。

因此,类型签名 ap Monad m => m(a - > b) - > m a - > m b 。你已经给它 zip tail 作为参数,所以让我们看看它们的类型签名。

tail :: [a] - > [a]〜( - >)[a] [a] (这里是类型的相等运算符)键入 ap

 ( - >)[x] [x]〜ma 
(( - >)[x])[x]〜ma

$ b $($ - $)$($ - $)$($ - $)$($ - $) ( - >)a)。我们已经可以看到我们所在的monad是( - >)[x] ,而不是 [] 。如果我们用 ap 的类型签名替换我们可以得到的:

 <$ c $ ((( - >)[x])([x]→> b)) - > ((( - >)[x])[x]) - > (( - >)[x])b)

由于这不太可读, ([x] - >([x] - > b)) - >([x] - > ([x]→> [x]) - > ([x]→b)
〜([x]→> [x]→> b)→> ([x]→> [x]) - > ([x] - > b)

zip [x] - > [y] - > [(x,y)] 。我们已经可以看到这与第一个参数一致: ap 其中

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

这里我已经列出了垂直类型,以便您可以轻松查看哪些类型排列。所以显然 x〜x y〜x [(x,y)] 〜[(x,x)]〜b ,所以我们可以将 b〜[(x,x)] 代入 ap 的类型签名并获得

 ([x]  - > [x] - > [(x,x)]) - > ([x]→> [x]) - > ([x]  - > [(x,x)])
- 拉链尾(ap zip尾)
- ap zip尾u =拉链u(尾u)

我希望能为您解决问题。

编辑:正如 danvari ,monad ( - >)a 有时被称为读者monad。

I wondered how to write f x = zip x (tail x) in point free. So I used the pointfree program and the result was f = ap zip tail. ap being a function from Control.Monad

I do not understand how the point free definition works. I hope I can figure it out if I can comprehend it from the perspective of types.

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

By looking at the expression ap zip tail I would think that zip is the first parameter of ap and tail is the second parameter of ap.

Monad m => m (a -> b) -> m a -> m b
           \--------/   \---/
              zip        tail

But this is not possible, because the types of zip and tail are completely different than what the function ap requires. Even with taking into consideration that the list is a monad of sorts.

解决方案

So the type signature of ap is Monad m => m (a -> b) -> m a -> m b. You've given it zip and tail as arguments, so let's look at their type signatures.

Starting with tail :: [a] -> [a] ~ (->) [a] [a] (here ~ is the equality operator for types), if we compare this type against the type of the second argument for ap,

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

we get a ~ [x] and m ~ ((->) [x]) ~ ((->) a). Already we can see that the monad we're in is (->) [x], not []. If we substitute what we can into the type signature of ap we get:

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

Since this is not very readable, it can more normally be written as

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

The type of zip is [x] -> [y] -> [(x, y)]. We can already see that this lines up with the first argument to ap where

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

Here I've listed the types vertically so that you can easily see which types line up. So obviously x ~ x, y ~ x, and [(x, y)] ~ [(x, x)] ~ b, so we can finish substituting b ~ [(x, x)] into ap's type signature and get

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

I hope that clears things up for you.

EDIT: As danvari pointed out in the comments, the monad (->) a is sometimes called the reader monad.

这篇关于表达式“ap zip tail”是如何工作的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆