Kotlin強行模擬Point-Free

原文保留完整格式

昨天在學習Haskell的過程中了解了什麼是Point-Free風格,然後瞬間中毒。於是我就打算在Kotlin裡面模擬一下。

這是Haskell中不Point-Free的版本:

generate :: (Num a, Enum a) => [a] -> [a]n-- not point freengenerate ls = zipWith (*) [0..] lsn

引用大魔頭在他的Haskell教程裡面說過的一句話,

兩邊約掉個參數

於是我們可以寫出Point-Free的版本:

generate :: (Num a, Enum a) => [a] -> [a]n-- point freengenerate = zipWith (*) [0..]n

然後我就嘗試把它翻譯為Kotlin。

解釋

首先向各位看不懂Haskell的看官解釋一下什麼是Point-Free。

柯里化

先假設Kotlin自帶柯里化,也就是說,我定義函數

fun a(a: Int,b: Int) = a + bn

之後,我可以這樣調用

val x = a(1)nval y = x(2)nprint(y) // 3n

Point-Free

然後我可以這樣:

fun plus1(x: Int) = a(1)(x)n

對吧,就是一個返回參數+ 1的函數。

這是不Point-Free的寫法。

fun plus1() = a(1)n

這是Point-Free的寫法。很簡單吧。

Kotlin強行模仿

因為標準庫沒有zipWith這個函數,所以我們先寫一個,然後手動柯里化了:

fun <A, B, C : Any> zipWith(op: (A, B) -> C) = { x: Sequence<A> ->n { y: Sequence<B> ->n val iX = x.iterator()n val iY = y.iterator()n generateSequence {n if (iX.hasNext() and iY.hasNext()) op(iX.next(), iY.next())n else nulln }n }n}n

此處使用了惰性序列Sequence來模擬Haskell的惰性求值,然後使用返回帶參數的Lambda的方式模擬柯里化。

然後寫個那個破函數:

fun generate() = zipWith { x: Int, y: Int -> x * y } (n generateSequence(0, Int::inc)n)n

對比Haskell的兩行:

generate :: (Num a, Enum a) => [a] -> [a]ngenerate = zipWith (*) [0..]n

很簡單吧?調用就是這樣:

fun main(args: Array<String>) {n generate()(sequenceOf(1, 1, 2, 3, 5, 8, 13, 21))n // .forEach(::println)n}n

把那行注釋取消了就是輸出。

對比Haskell的調用:

generate [1, 1, 2, 3, 5, 8, 13, 21]n

Easy~

完整的代碼

我把完整的代碼貼到了我的gist上。

試下調用gist的API(很可能需要翻牆才能看到)(很可惜知乎不支持這格式):

package mainnn/**n * Created by ice1000 on 2017/4/27.n *n * @author ice1000n */nnfun <A, B, C : Any> zipWith(op: (A, B) -> C) = { x: Sequence<A> ->nt{ y: Sequence<B> ->nttval iX = x.iterator()nttval iY = y.iterator()nttgenerateSequence {ntttif (iX.hasNext() and iY.hasNext()) op(iX.next(), iY.next())ntttelse nullntt}nt}n}nnfun <T : Any> generate() = {ntzipWith { x: Int, y: T -> "[$y * x^$x]" }(ntttgenerateSequence(0, Int::inc)nt)n}nnfun main(args: Array<String>) =nttgenerate<Int>()()(sequenceOf(1, 1, 2, 3, 5, 8, 13, 21))ntttt.forEach(::println)nn// view rawpoint-free.kt hosted with ? by GitHubn

推薦閱讀:

GHC API 系列筆記(1):入門篇
仙境里的Haskell(之二)
Equational Reasoning的含義是什麼?

TAG:Kotlin | Haskell | 函数式编程 |