Haskell部分应用函数,派生类型

Mik*_*ael 4 haskell

在GHCI前奏>使用:t中查找函数的类型:

(.) :: (b -> c) -> (a -> b) -> a -> c

(:) :: a -> [a] -> [a]

((.)(:)) :: (a -> b) -> a -> [b] -> [b]   -- (what happened here?)
Run Code Online (Sandbox Code Playgroud)

我理解单个函数的结果,但是当部分应用时我没有.

地图的类型是什么?我在这个页面上找到了答案,如何以代数方式进行.但是我在使用相同的方法时遇到了问题((.)(:)).

当你想知道什么类型的方法是((.)(:))什么?有没有一种思维方式可以用于函数的任何部分应用?

提前致谢.

Ric*_* T. 9

当您想要推断部分应用程序的类型时,最好的办法是从构建块的最常见类型开始,并搜索您正在编写的类型之间的匹配.让我通过描述你为你所搜索的类型所遵循的推理来更清楚地说明这一点.

首先,让我们重命名类型变量,(:)以避免混淆:

(.) :: (b -> c) -> (a -> b) -> a -> c
(:) :: d -> [d] -> [d]
Run Code Online (Sandbox Code Playgroud)

(.) (:)部分适用(:)(.),仅提供其第一个参数.这意味着第一个参数(.),即类型的(b -> c),被实例化到(d -> ([d] -> [d])),具有b == dc == ([d] -> [d])(记住,->是右结合).

如果在整个事物中应用此类型替换,则会得到部分应用(.)失去其第一个参数(已被修复为(:))并导致(a -> d) -> a -> ([d] -> [d]),这相当于(a -> d) -> a -> [d] -> [d](再次,通过右关联性):这是类型表达式你来自ghci.


Mat*_*ick 6

扩展@ Riccardo的答案:

  1. 类型签名的对应关系

    (b  ->       c     )       -- first argument of (.)
    (d  ->  ([d] -> [d])       --   corresponds to type of (:)
    
    Run Code Online (Sandbox Code Playgroud)
  2. 代换

    (a -> b) -> a ->      c    -- rest of (.)'s type, minus first argument
    
    Run Code Online (Sandbox Code Playgroud)

    (a -> d) -> a -> ([d] -> [d])
    
    Run Code Online (Sandbox Code Playgroud)
  3. 正确的联想

    (a -> d) -> a -> [d] -> [d]
    
    Run Code Online (Sandbox Code Playgroud)