2016-07-28 3 views
10

K-combinatorは以下のように実装することができ、実装に副作用があってはいけません。javascriptでのK-combinator(Kestrel)の実際の使用

const K = x => y => x; 

「const」(Haskellのように)と呼ばれることがあります。 K関数は、「値をとり、常にその値を返す(定数)単項関数を返します」と定義されている可能性があります。

いつ便利ですか?実践的な事例を教えてください。

+0

http://cs.stackexchange.com/questions/55441/what-is-the-purpose-of-the-ski-combinator-calculusor-even-lambda-calculus- wha –

+0

非常に便利なCL関数[constanty](http://clhs.lisp.se/Body/f_cons_1.htm)のようです。 – Sylwester

+3

カレー言語では、最初の引数をコールバックで無視する場合に使用します。 – Bergi

答えて

2

Kの問題は、すべてのプリミティブコンビネータと同様に、単独では考慮できないことです。プリミティブコンビネータは、関数型プログラミングの基本ブロックです。あなたは仕事でそれらを見るために適切なコンテキストが必要です。あなたが機能的なパラダイムに慣れていないなら、この文脈を突き詰めることが課題です。

ここには「典型的な文脈」があります:Optionです。 Optionタイプのインスタンスがnullかもしれ値のようなものですが、機能に適用された場合、エラーをスローすることはありません:

// the option type 
 

 
const Option = { 
 
    some: Symbol.for("ftor/Option.some"), 
 

 
    none: Symbol.for("ftor/Option.none"), 
 

 
    of: x => factory(Option.some) (x), 
 

 
    cata: pattern => o => pattern[o.tag](o.x), 
 

 
    fold: f => g => o => Option.cata({[Option.some]: f, [Option.none]: g}) (o), 
 

 
    map: f => o => Option.fold(x => Option.of(f(x))) (K(o)) (o) 
 
    //            ^^^^ 
 
} 
 

 

 
// a generic map function 
 

 
const map = type => f => o => type.map(f) (o); 
 

 

 
// functor factory 
 

 
const factory = tag => value => (
 
    {x: value === undefined ? null : value, tag: tag} 
 
); 
 

 

 
// auxiliary functions 
 

 
const K = x => y => x; 
 
const sqr = x => x * x; 
 

 

 
// a few data to play around 
 

 
const o = factory(Option.some) (5); 
 
const p = factory(Option.none)(); 
 

 

 

 
// and run 
 

 
let r1 = map(Option) (sqr) (o); 
 
let r2 = map(Option) (sqr) (p); 
 

 
console.log("map over o", r1); 
 
console.log("map over p", r2);

Kは、この実装では何をしますか?のは、決定的なラインを見てみましょう:

f => o => Option.fold(x => Option.of(f(x))) (K(o)) (o) 

Option.foldは2つの機能を期待しています。最初に渡された関数x => Option.of(f(x))は、someの場合です(値があります)。 2番目はnoneの場合のK(o)です(値はありません)。 Kは2つの引数K = x => y => {return x}を期待していることを思い出してみましょう。 K(o)oxに割り当てます。第2引数として渡された内容に関係なく、Kは常にyを無視し、代わりにxを返します。

oは式K(o)の中で何を表していますか?それはOption.noneを表します。つまり、値が存在しません。したがって、fnoneにマップしようとすると、fKに渡されても、noneが返されます。

+0

前提条件関数 "precon"はどこにありますか? –

1

教会でコード化されたブーリアンを使用する場合、Kコンビネータを真理値として使用することもできます。 I. IF-TEST THEN ELSE: "IF-TEST"がKを返した場合、 "else"が削除され、 "then"が実行されます。

+0

すべてのコードスニペット? –

2

よくある質問ですが、好きです。私はそれが好きです。

私の例をサポートするために、この回答では&hellipを実装します。

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

…型が示唆するように、配列を構築するための数と関数を取ります。これは、ある計算に基づいて既知のサイズの配列を作成する場合に便利です。


アイデンティティ関数idを使用して5つの要素で配列を作成しましょう。あなたが見ることができるように、0から始まる連続的な数値指標は、あなたのビルダー機能

abuild(5)(ID) // => [0,1,2,3,4]

に与えられ、

今回は建築家と数学をしましょう。入力を正方形にします。非常に高度な。

abuild (5) (x=> x * x) 
// => [0,1,4,9,16] 

おそらく入力については気にしません。私はいつも良い笑いが大好きです。私は物事を絶えず笑う。 1つは私が言うことができるK('ha')…

abuild (5) (K('ha')) 
// => ['ha','ha','ha','ha','ha'] 

ブーム!かなり便利ですよね?それは

は先に行くと行動でKを見るためにそれを実行K


実装です!

// id :: a -> a 
 
const id = x=> x 
 

 
// K :: a -> b -> a 
 
const K = x=> y=> x 
 

 
// add :: Number -> Number -> Number 
 
const add = x=> y=> y + x 
 

 
// reduce :: (a -> b) -> b -> [a] -> b 
 
const reduce = f=> y=> ([x,...xs])=> { 
 
    if (x === undefined) 
 
    return y 
 
    else 
 
    return reduce (f) (f (y) (x)) (xs) 
 
} 
 

 
// map :: (a -> b) -> [a] -> [b] 
 
const map = f=> reduce (xs=> x=> [...xs, f(x)]) ([]) 
 

 
// iterate :: Number -> (a -> a) -> a -> [a] 
 
const iterate = n=> f=> x=> 
 
    n > 0 ? [x, ...iterate (n - 1) (f) (f(x))] : [] 
 

 
// abuild :: Number -> (Number -> a) -> [a] 
 
const abuild = n=> f=> 
 
    map (f) (iterate (n) (add (1)) (0)) 
 

 
console.log(abuild (5) (id)) 
 
// => [0,1,2,3,4] 
 

 
console.log(abuild (5) (x=> x * x)) 
 
// => [0,1,4,9,16] 
 

 
console.log(abuild (5) (K('ha'))) 
 
// => ['ha','ha','ha','ha','ha']

+0

私はユーモアのある機能が好きです:D 'K(" ha ")'は誰かと笑っていますか? – ftor

+1

それは私に少しの洞察です!私はどんな状況の光も作りたいです^ _ ^ – naomik

関連する問題