类型签名Hindley-Milner | 函数式编程

522 阅读3分钟

辨别类型和它们的含义是一项重要的技能,这项技能可以让你在函数式编程的路上走得更远。不仅论文、博客和文档等更易理解,类型签名本身也基本上能够告诉你它的函数性(functionality)。

背景: 在使用ramdajs这个函数工具库时每个函数下面都有一行类型签名,据说类型签名包含大量信息,阅读类型签名我们可以获知函数的传参与返回类型等等,没学它之前我是不信的,今天看来它和ts一样“真香”,今天来捋一下类型签名,看它到底香不香。

类型签名基本知识

// head :: [T] -> T

上面便是一个类型签名,head为函数名, T为类型, ->为处理过程,最后一个T为返回参数类型, 通过阅读类型签名可以把它翻译为typescript如下:

function head<T>(a: Array<T>):T;

Hindley-Milner里面的类型具有多态性(polymorphism),类似ts里面的泛型(Generics)比如类型T即可以为Number, 也可以为String等等基本类型。

如果参数是函数时,类型签名这样写:

//  map :: (a -> b) -> [a] -> [b]

上面的类型签名理解如下:

  1. 第一个参数为函数(a->b),函数接收类型为a的参数, 里面的-> 可以理解为处理过程,返回类型为b。
  2. 中间的-> [a], 接收第二个参数[a]: 数组类型为a, 函数式编程的世界,所以的函数都被柯里化了,所以中间的 -> x都理解为接收参数x.
  3. 最后的 -> [b]为返回值, 返回类型为b的数组。

typescript改写如下:

function map<a, b>(fn: (item:a) => b, list: Array<a>):Array<b>;

ramdajs例子

看完这些实用例子,加深你对类型签名的理解,要还不明白可以过来打我。

pluck

Functor f => k → f {k: v} → f v

这个例子里面, 我们可以接触到类型约束, 写法如下: 约束名 变量 =>

Functor f =>

类型约束类似于typescript里的interface(接口),上面的f变量受Functor的约束,点击文档可知f只能为数组或者对象。 类型签名解释:输入k类型,输入 {x: {k: v}} 或者 [{k: v}], 输出: {x: v} 或者 [v]

const R = require('ramda');
var getAges = R.pluck('age');
getAges([{name: 'fred', age: 29}, {name: 'wilma', age: 27}]); //=> [29, 27]

composeWith

((* → *), [(y → z), (x → y), …, (o → p), ((a, b, …, n) → o)]) → ((a, b, …, n) → z)

这个例子够复杂吧,我就解释一下它,看能不能把我自己绕晕...

  1. 输入
// 接收2个参数
// ((* → *), [(y → z), (x → y), …, (o → p), ((a, b, …, n) → o)])
// 第一个是函数(* -> *), *指参数不限
// 第二个是数组 [(y → z), (x → y), …, (o → p), ((a, b, …, n) → o)],里面的内容为函数
// 根据观察可以发下数据处理流从右到左, 最后返回z
// (a, b, ..., n) -> o -> p ... -> x -> y -> z
  1. 输出
// 返回一个函数 (a,b, ..., n) -> z
// 这是可以和输入的第二个参数做对比,下面是分析输入得出的结果 
// (a, b, ..., n) -> o -> p ... -> x -> y -> z
// 可以发下输入,输入都一样,结合compose这个单词的意思:(组合)
// 可以猜测: 输入(a, b, ..., n) -> 一系列函数处理 输出 z
const R = require('ramda');
const composeWhileNotNil = R.composeWith((f, res) => R.isNil(res) ? res : f(res));
composeWhileNotNil([R.inc, R.prop('age')])({age: 1}) //=> 2
composeWhileNotNil([R.inc, R.prop('age')])({}) //=> undefined

解释的还是不够透彻,大佬可以在评论区留言解释composeWith的类型签名...

学习推荐

llh911001.gitbooks.io/mostly-adeq…