K-combinator可以按照下面的方式实现,实现不应该有任何副作用。K-combinator(Kestrel)在javascript中的实际应用
const K = x => y => x;
它有时被称为“const”(如在Haskell中)。 K函数可能被定义为,“接受一个值并返回一个总是返回该值的(常量)一元函数。”
什么时候有用?请以实际例子帮助我。
K-combinator可以按照下面的方式实现,实现不应该有任何副作用。K-combinator(Kestrel)在javascript中的实际应用
const K = x => y => x;
它有时被称为“const”(如在Haskell中)。 K函数可能被定义为,“接受一个值并返回一个总是返回该值的(常量)一元函数。”
什么时候有用?请以实际例子帮助我。
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
需要两个功能。第一个传递的函数x => Option.of(f(x))
用于some
的情况(有一个值)。第二个K(o)
为none
的情况(没有值)。我们记得K
需要两个参数K = x => y => {return x}
。 K(o)
分配o
至x
。无论通过第二个参数,K
将始终忽略y
,并返回x
。
但o
代表K(o)
表示什么?它代表Option.none
即没有价值。因此,当有人试图通过none
映射函数f
时,仅返回none
,无论f
作为第二个参数传递给K
。
预处理函数“precon”在哪里? –
当使用教会编码的布尔值时,K combinator也可以用作真值。 也就是说IF-TEST then else:如果你的“IF-TEST”返回K,那么“else”将被丢弃,然后“then”被执行。
任何代码片段? –
排序的一个广泛的问题,但它很好,我喜欢它。
为了支持我的例子,在这个答案中,我将实现…
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]
或者我们可能不关心输入。我一直都很喜欢笑。我不断地嘲笑事情。人们可以说我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']
http://cs.stackexchange.com/questions/55441/what-is-the-purpose-of-the-ski-combinator-calculusor-even-lambda-calculus- wha –
它看起来像CL函数[constanty](http://clhs.lisp.se/Body/f_cons_1.htm),它有时非常有用。 – Sylwester
在咖喱语言中,只要您希望回调忽略第一个参数,就可以使用它。 – Bergi