0

左側が例外/エラーを表し、2 番目の側が戻り値を格納する、Either のインスタンスを返す関数があります。

Each インスタンスが 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 (Node 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()

これらの 2 つのヘルパー関数を使用して

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に屈することができないのか理解していませんが、それは別の問題です)。

左側はそうではないのに、右側をどちらかに戻す必要がある理由がわかりません。

于 2015-11-18T20:46:44.067 に答える
0

これは私のコードの現在の状態であり、より良いと思います。まず、Maybe をいずれかに変換して、/ 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 に答える