首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >K-combinator (Kestrel)在javascript中的实际应用

K-combinator (Kestrel)在javascript中的实际应用
EN

Stack Overflow用户
提问于 2016-07-28 19:54:04
回答 4查看 2.1K关注 0票数 13

K-combinator可以像下面这样实现,并且该实现不应该有任何副作用。

代码语言:javascript
复制
const K = x => y => x;

它有时被称为"const“(在Haskell中)。K函数可以定义为“接受一个值并返回一个始终返回该值的(常量)一元函数”。

它什么时候有用?请用实际的例子来帮助我。

EN

回答 4

Stack Overflow用户

发布于 2016-08-03 16:25:27

这是一个宽泛的问题,但它很好,我喜欢它。

为了支持我的示例,在这个答案中,我将实现…

代码语言:javascript
复制
abuild :: Number -> (Number -> a) -> [a]

…正如类型所示,它接受一个数字和一个函数来构建一个数组。如果您想要根据一些计算构建一个已知大小的数组,这可能会很有用。

让我们使用标识函数id构建一个包含5个元素的数组。如您所见,向构建器函数提供了一个从0开始的顺序数字索引

abuild (5) (id) // => 0,1,2,3,4

这一次让我们对构建器做一些数学运算。我们将平方输入。非常先进。

代码语言:javascript
复制
abuild (5) (x=> x * x)
// => [0,1,4,9,16]

也许我们并不关心输入。我总是喜欢开怀大笑。我总是笑个不停。你可以说I K('ha')

代码语言:javascript
复制
abuild (5) (K('ha'))
// => ['ha','ha','ha','ha','ha']

轰隆隆!非常有用,对吧?那是K

Implementation

继续运行它,看看K是如何运行的!

代码语言:javascript
复制
// 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']

票数 7
EN

Stack Overflow用户

发布于 2016-07-28 23:36:33

与所有原语组合子一样,K的问题是您不能单独考虑它。基本组合器是函数式编程的基本构件。你需要一个合适的环境来观看他们的工作。如果您是函数范式的新手,那么挑战就是理解这个上下文。

这是一个“典型的上下文”:OptionOption类型的实例类似于可以为null的值,但在应用于函数时不会抛出错误:

代码语言:javascript
复制
// 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在这个实现中做了什么?让我们来看一下关键的一行:

代码语言:javascript
复制
f => o => Option.fold(x => Option.of(f(x))) (K(o)) (o)

Option.fold需要两个函数。第一个传递的函数x => Option.of(f(x))用于some的情况(有一个值)。none情况的第二个K(o) (没有值)。让我们回想一下,K需要两个参数K = x => y => {return x}K(o)o分配给x。无论作为第二个参数传递什么,K都将始终忽略y并返回x

但是,在表达式K(o)中,o代表什么呢?它表示Option.none,即缺少值的情况。因此,当有人试图将函数f映射到none上时,无论f作为第二个参数传递给K是什么,都只返回none

票数 5
EN

Stack Overflow用户

发布于 2016-07-29 13:43:13

当使用教会编码的布尔值时,K组合符也可以用作真值。即IF-TEST THEN ELSE:如果你的" if -TEST“返回K,那么"else”将被删除," then“将被执行。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38635615

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档