2017-07-03 8 views
3

にすべてのフィルタ機能を適用します。私はそれらを既存のbuilderの値に適用したいので、Noneの場合は、そのまま返します。は、私はこのように見える機能を有する値

上記のコードは私が思いつくことができる最高ですが、どういうわけかMonoidでこれを行うことができると感じています - Noneの場合はidentityを返してください。

残念ながら、わかりやすいものを定義する方法を理解できません。または、これを行う方法がより良い/異なる場合は、

私は猫を使用しています。何か案は?

+0

*なしの場合の身元を返す*アイデンティティを返します(。ゼロ)?意味は、 'Monoid [文字列] .zero'を空の文字列にするといいでしょうか? –

+0

@YuvalItzchakov hmm、最初の 'builder'を返すために' identity'関数を適用することを意味すると確信しています... –

+0

ああ、あなたは 'Monoid [Builder]'について話していますか? –

答えて

1

私はあなたの場合にはA => M[A]の構造が少し不必要だと思います。この例で使用するフィルタ関数は、実際にはOption[Builder => Builder]に相当します。結果がSomeまたはNoneのいずれであるかを判断するのに、Builder引数を使用しないためです。さらに、機能をBuilder => Builderに簡略化すると、.getOrElse(identity)となります。

このアイデアを使用する実装は2つあります。彼らは本当に猫に頼っていません。

def createBuilder(
    builder: InitialBuilder, name: Option[String], useCache: Boolean, timeout: Option[Long] 
): Builder = { 
    def builderStage[T](param: Option[T])(modify: T => Builder => Builder): Builder => Builder = 
    param.fold(identity[Builder](_))(modify) 

    val stages: List[Builder => Builder] = List(
    builderStage(name)(n => _ withName n), 
    // `Boolean` is equivalent to `Option[Unit]`, and we convert it to that representation 
    // Haskell has a special function to do such a conversion `guard`. 
    // In Scalaz you can use an extension method `useCache.option(())`. 
    // In cats a similar `option` is provided in Mouse library. 
    // But you can just write this manually or define your own extension 
    builderStage(if (useCache)().some else none)(_ => _.withCache), 
    builderStage(timeout)(t => _ withTimeout t) 
) 

    // It should be possible to use `foldK` method in cats, to do a similar thing. 
    // The problems are that it may be more esoteric and harder to understand, 
    // it seems you have to provide type arguments even with -Ypartial-unification, 
    // it folds starting from the last function, because it's based on `compose`. 
    // Anyway, `reduceLeft(_ andThen _)` works fine for a list of plain functions. 
    stages.reduceLeft(_ andThen _)(builder) 
} 

もう一つの可能​​性はflattenに単にidentityにそれらを強制することなく、None秒を削除しListOptionのS、次のとおりです。

def createBuilder2(
    builder: InitialBuilder, name: Option[String], useCache: Boolean, timeout: Option[Long] 
): Builder = { 
    val stages: List[Option[Builder => Builder]] = List(
    name.map(n => _ withName n), 
    if (useCache) Some(_.withCache) else None, 
    timeout.map(t => _ withTimeout t) 
) 

    stages.flatten.reduceLeft(_ andThen _)(builder) 
} 
+0

驚くべき!ありがとう、確かに探検する価値のある素晴らしいアイデア! –

関連する問題