0

我有一个函数,它返回一个 Either 实例,其中左侧表示异常/错误,而第二侧存储返回值。

如果 Either 实例已被实例化到 Error 分支,我想立即返回。如果该实例已被 Right 实例化,我想将其包装在 Maybe 中并继续(因为它作为 Maybe 进入函数,并且仅在它为 Nothing 时才被查找)。

这是根据我的测试用例工作的:

  1. isNothing 传入 :: 查找错误
  2. isNothing 传入 :: 查找成功
  3. isJust(22) 被传入(查找不执行)

代码感觉不错,但我不怀疑我可能会错过 Folktale data.either 库的一些细节。

// from data.monad
const someValue = Maybe.Nothing()

// ...snip...

if (someValue.isNothing) {

    // from data.either :: Either.Left | Either.Right
    const possiblySomeValue = yield lookupSomeValue()
    if(possiblySomeValue.isLeft) {
        return possiblySomeValue
    } else {
        someValue = Maybe.Just(possiblySomeValue.get())
    }
}

我将 ES6(节点 4.1)与 Folktale 结合起来:data.either 和 data.maybe。我的目标是真正提高我对如何以这种风格正确写作的理解


更新问题有点复杂我背靠背独立查找,我觉得可以链接在一起:

// from data.monad
const someValue = Maybe.Nothing()

// ...snip...

if (someValue.isNothing) {

    // from data.either :: Either.Left | Either.Right
    const possiblySomeValue = yield lookupSomeValue()
    if(possiblySomeValue.isLeft) {
        return possiblySomeValue
    } else {
        someValue = Maybe.Just(possiblySomeValue.get())
    }
}

// from data.monad
const someValue2 = Maybe.Nothing()

// ...snip...

if (someValue2.isNothing) {

    // from data.either :: Either.Left | Either.Right
    const possiblySomeValue2 = yield lookupSomeValue2()
    if(possiblySomeValue2.isLeft) {
        return possiblySomeValue2
    } else {
        someValue2 = Maybe.Just(possiblySomeValue2.get())
    }
}

它的背靠背事件使代码超级难看......

4

2 回答 2

0

也许(完全是双关语)更好的方法

const someValue = (yield maybeToEither(maybeSomeValue).cata({
    Left: lookupSumValue,
    Right: yieldableRight})).get()

使用这两个辅助函数

const yieldableRight = function(value){
    return function*(){ return Either.Right(value) }
}

const maybeToEither = function(maybe) {
    if (maybe.isNothing) {
        return Either.Left(undefined)
    } else {
        return Either.Right(maybe.get())
    }
}

其中 lookupSomeValue 的形式为(返回生成器的函数):

const lookupSomeValue = function(){
    return ((function *(){
        return 10
    })())
}

问题是右侧需要返回一些可屈服的东西。出于某种原因,Koa/Co 在 Either.Right() 上窒息(即使对象是可屈服的),作为可屈服的——所以我返回了一个返回值的生成器。我明白了(我不明白为什么我不能屈服于 Either.Right,但那是一个不同的问题)。

我不明白为什么右侧需要被包裹在一个 Either 中,而左侧则不需要。

于 2015-11-18T20:46:44.067 回答
0

这是我认为更好的代码的当前状态。首先能够将 Maybe 转换为 any,以允许我使用转换链接 / orElse(Maybe.orElse 不允许采用函数,而 Either.orElse 确实采用转换函数)

const maybeToEither = function(maybe) {
    if (maybe.isNothing) {
        return Either.Left(undefined)
    } else {
        return Either.Right(maybe.get())
    }
}

然后,由于我将 Maybe.Just 解包到 Either.Right 作为转换的一部分,我只需要提供 orElse 转换。

const someValue = maybeToEither(maybeSomeValue).orElse(function(ignore){
    return lookupSumValue()
}).get()

融入我的实际问题,生成器会导致一个稍微难看的解决方案。lookupSomeValue 是一个生成器函数,所以我们需要 yield。此外,由于该值在多个地方使用,我们希望通过 get 将其强制为一个值。

const someValue = (yield maybeToEither(maybeSomeValue).orElse(function(ignore){
    return lookupSumValue()
})).get()

所以当重复时,代码并不像我原来的解决方案那么糟糕 -

const someValue = (yield maybeToEither(maybeSomeValue).orElse(function(ignore){
    return lookupSumValue()
})).get()

const someValue2 = (yield maybeToEither(maybeSomeValue2).orElse(function(ignore){
    const someRandom = getRandom()
    return lookupSumValue2(someRandom)
})).get()

我仍在寻找更简洁的语法。如果我找到一个解决方案,将使用另一种解决方案进行更新。

于 2015-11-18T18:45:55.663 回答