成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Ramda 哪些讓人困惑的函數簽名規則

開發 前端
在類型簽名中F?是一個類型構造器, 既和Array一樣的 「返回類型的類型」, 然而, TypeScript 里根本無法聲明"一個類型參數為類型構造器"。

在我們查閱 Ramda 的文檔 時, 常會見到一些"奇怪"的類型簽名和用法,例如:

(Applicative f, Traversable t) => (a → f a) → t (f a) → f (t a)

或者,某一些函數"奇怪"的用法:

// R.ap can also be used as S combinator // when only two functions are passed 
R.ap(R.concat, R.toUpper)('Ramda') //=> 'RamdaRAMDA'

這些"奇怪"的點背后投射著 Ramda "更深"一層的設計邏輯, 本文將會對此作出講解, 并闡述背后通用的函數式編程理論知識。

Ramda 為人熟知的一面?

Ramda 經常被當做 Lodash 的另外一個"更加FP"的替代庫,相對于 Lodash,Ramda 的優勢(之一)在于完備的柯里化與 data last 的設計帶來的便捷的管道式編程(pipe)。

舉一個簡單的代碼對比示例:

  • Ramda:
const myFn = R.pipe (
R.fn1,
R.fn2 ('arg1', 'arg2'),
R.fn3 ('arg3'),
R.fn4
)
  • Lodash:
const myFn = (x, y) => {
const var1 = _.fn1 (x, y)
const var2 = _.fn2 (var1, 'arg1', 'arg2')
const var3 = _.fn3 (var2, 'arg3')
return _.fn4 (var3)
}

Ramda 類型簽名?

在 Ramda 的 API 文檔中, 類型簽名的語法有些"奇怪":

  • add: Number → Number → Number

我們結合 Ramda 的柯里化規則, 稍加推測, 可以將這個函數轉換為TypeScript 的定義:

export function add(a: number, b: number): number;
export function add(a: number): (b: number) => number;

OK, 那為什么Ramda 的文檔不直接使用TypeScript 表達函數的類型呢? -- 因為更加簡潔!

Ramda 文檔中的類型簽名使用的是Haskell 的語法, Haskell 作為一門純函數式編程語言, 可以很簡潔地表達柯里化的語義, 相較之下, TypeScript 的表達方式就顯得比較臃腫。

當然, 使用Haskell 的類型簽名的意義不僅于此, 讓我們再看看其他"奇怪"的函數類型:

  • ap:
[a → b][a][b]
Apply f => f (a → b) → f a → f b
(r → a → b)(r → a)(r → b)

結合文檔中的demo:

R.ap([R.multiply(2), R.add(3)], [1,2,3]); //=> [2, 4, 6, 4, 5, 6]

R.ap([R.concat('tasty '), R.toUpper], ['pizza', 'salad']); //=> ["tasty pizza", "tasty salad", "PIZZA", "SALAD"]

// R.ap can also be used as S combinator
// when only two functions are passed
R.ap(R.concat, R.toUpper)('Ramda') //=> 'RamdaRAMDA'

[a → b] → [a] → [b]我們好理解, 就是笛卡爾積;

(r → a → b) → (r → a) → (r → b)我們也能理解, 就是兩個函數的串聯;

Apply f => f (a → b) → f a → f b就有點難理解了, 語法上就有些陌生, 我們先將其翻譯成TypeScript 語法:

:), 好吧, 這段類型沒法簡單地翻譯成TypeScript, 因為: TypeScript 不支持將 「類型構造器」 作為類型參數!舉個例子:

type T<F> = F<number>;

報錯信息如下:

Type 'F' is not generic.

在類型簽名中F?是一個類型構造器, 既和Array一樣的 「返回類型的類型」, 然而, TypeScript 里根本無法聲明"一個類型參數為類型構造器"。

正如示例中type T<F> = F<number>;?中, 我們無法告訴TypeScript, 這里的F?是一個類型構造器, 所以當將number?傳入F的時候, 就報錯了。

OK, 我們假設TypeScript 支持聲明"一個類型參數為類型構造器", 讓我們再來看看Apply f => f (a → b) → f a → f b該怎么翻譯:

type AP = <F extends Appy, A, B>(f: F<((a: A) => B)>) => (fa: F<A>) => F<B>;

這里的F可以理解為一種 「上下文」, 這段類型簽名可以先簡單地理解為:

將一個包裹在上下文中的「函數」取出, 再將另一個包裹在上下文中的「值」取出, 調用函數后, 將函數的返回值重新包裹進上下文中并返回。

這里的 「上下文」 是一個泛指, 比如我們可以將其特異化(specialize)為 Promise :

type AP = <A, B>(f: Promise<((a: A) => B)>) => (fa: Promise<A>) => Promise<B>;  
const ap: AP = (f) => fa => f.then(ff => fa.then(ff));

ap? 或說 Apply 作為函數式編程中的一種常見抽象, 有非常重要重要的學習意義, 但其抽象的解析超出本文范圍, 在這里我們只聚焦于「是什么」, 暫不考慮「為什么」。

那么, (r → a → b) → (r → a) → (r → b)與Apply f => f (a → b) → f a → f b是什么關系?

他們之間是同父異母的關系, (r → a → b) → (r → a) → (r → b)?是對Apply f => f (a → b) → f a → f b的特異化, 正如我們對Promise 做的那樣。

函數也可以是一個 「上下文」?

答案是可以的, 我們可以將一個一元函數a -> b?理解為"一個包裹在上下文中的b?, 只不過為了獲取這個b?, 需要先傳入一個a。

先看看 Haskell 對ap 的定義:

instance Applicative ((->) r) where
(<*>) f g x = f x (g x)

替換為TypeScript 的實現, 我們將上面的Promise 的例子稍微修改下, 得出:

type F<A> = (a: any) => A;

type AP = <A, B>(f: F<((a: A) => B)>) => (fa: F<A>) => F<B>;

const ap: AP = f => fa => {
return (r) => f(r)(fa(r));
}

同樣的, 我們得到Apply 特異化為Array 的實現:

type AP = <A, B>(f: Array<((a: A) => B)>) => (fa: Array<A>) => Array<B>;

const ap: AP = f => fa => {
return f.flatMap(ff => fa.map(ff));
};

綜上所述, 我們可以得出結論:

ap的類型簽名[a → b] → [a] → [b]和(r → a → b) → (r → a) → (r → b)是Apply f => f (a → b) → f a → f b的特異化。

責任編輯:武曉燕 來源: Tecvan
相關推薦

2012-04-25 10:18:49

jQuery

2021-08-26 15:44:33

路由函數ASP

2009-08-14 09:19:15

Windows 7XP模式優缺點

2011-09-15 09:19:30

2020-01-14 18:20:48

OA選型CIO

2015-09-21 14:44:54

物聯網

2018-05-03 08:13:35

2015-02-11 15:40:40

XY蘋果助手iOS9

2023-11-28 12:19:49

C++函數指針

2021-01-07 08:05:20

JenkinsDevOps

2023-01-03 17:51:05

2015-06-08 09:18:53

軟件永生軟件規則

2025-03-10 00:17:00

2009-09-25 15:15:17

算法

2016-03-31 16:50:54

2021-03-26 06:36:50

安全軟件殺毒軟件免費安全軟件

2022-03-04 06:46:30

Python代碼

2022-07-29 11:02:17

Web3NFT元宇宙

2015-08-25 08:55:14

優秀代碼基因

2022-03-04 09:43:18

UDP日志TCP
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产色片在线 | 欧美激情精品久久久久久变态 | 国产精品欧美一区二区三区不卡 | 狠狠的干 | 国产美女在线精品免费 | 国产欧美一区二区三区在线看 | 香蕉大人久久国产成人av | 三区在线观看 | 超碰97免费在线 | 免费一级网站 | 国产精品久久久久aaaa九色 | 久草网站| 日本在线视频不卡 | 久久久久久精 | 男女啪啪高潮无遮挡免费动态 | 欧美一区二区三区在线视频 | 亚洲精品一区二区三区在线 | 欧美成年网站 | 精品国产伦一区二区三区观看方式 | 国产成人精品福利 | 国产超碰人人爽人人做人人爱 | 国产成人a亚洲精品 | 九九在线视频 | 亚洲国产精品久久久 | 国产精品国产精品 | 亚洲高清视频一区二区 | 中文字幕人成乱码在线观看 | 男人天堂99 | 毛片在线视频 | 久久久久久久一区 | 日韩免 | 特黄视频| 国产精品久久久久久婷婷天堂 | 国产精品网页 | 国产精品美女久久久久久久久久久 | 久久亚洲春色中文字幕久久久 | 国产伦精品一区二区三区视频金莲 | 国产成人精品一区二区 | 精品美女在线观看 | 日韩福利电影 | 国产福利在线播放 |