2016-12-29 6 views
1

に終了し、私は種類を作成しScalaz:それは私はモナド変圧器を勉強なし

それらを配列決定し、問題を持っていないので、タイプOptionT [州立[_]、T]のモナドを組み合わせる方法OptionTBitSetState[T]

I署名付き機能ステップを有する

import scalaz._, Scalaz._ 
import scala.collection.immutable.BitSet 

type BitSetState[T] = State[BitSet, T] 
type OptionTBitSetState[T] = OptionT[BitSetState, T] 
object OptionTBitSetState { 
    def apply[T](option : Option[T]) : OptionT[BitSetState, T] = 
    OptionT[BitSetState, T](State[BitSet, Option[T]](_ -> option)) 

    def apply[T](state : State[BitSet, T]) : OptionT[BitSetState, T] = 
    OptionT[BitSetState, T](state.map(_.some)) 
} 

を失敗する可能性があり、ステートフル計算ように私は、この種の理解

def step(i : Int) : OptionTBitSetState[Seq[Int]] 

この機能すべきである:それは含まれている場合のBitSetにiを追加し、Seq(i, i*10, i*100)

  • を返す:

    1. チェックそれが含まれていない場合は国家内部のBitSetは、パラメータi
      • が含まれている場合:失敗するとNone
    2. 機能 ステップ

    実装:

    def step(i : Int) : OptionTBitSetState[Seq[Int]] = 
        for { 
        usedIs <- OptionTBitSetState(get[BitSet]) 
        res <- OptionTBitSetState(
         Some(Seq(i, i*10, i*100)).filterNot(_ => usedIs.contains(i)) 
        ) 
        _ <- OptionTBitSetState(put(usedIs + i)) 
        } yield res 
    

    私はこのシーケンスを評価するとき、私は結果としてオプションのリストを取得するようにステップのリストを順序付けるしたいです。しかし、sequenceの署名が異なります。代わりにリストのオプションがあります。

    List(1,2,1,3).map(step).sequence.run(BitSet.empty) 
    

    戻りNoneが、何が欲しいです:

    List(Some(Seq(1, 10, 100)), Some(Seq(2, 20, 200)), None, Some(Seq(3, 30, 300))) 
    

    は私がOptionTBitSetState[T]を組み合わせることができます任意の方法はありますので、私は、私は必要な動作を得るのだろうか?

  • 答えて

    2

    私の謙虚な意見では、あなたはOptionTを使用して解決策を複雑にしています。

    OptionTの問題は、モナド内部の値を既存のものとして扱うか、または存在しないものとして扱うことです。したがって、個々の計算を単一の状態に崩壊させて実行すると、失敗する。

    私はちょうどState[BitSet,Option[Seq[Int]]を使用します。私はScalaを特によく話さないので、ここでは(簡単にするために若干変更されています)Haskellのバージョンです。あなたが本当に欲しい

    module Main where 
    
    import Control.Monad.State 
    import Data.IntSet (IntSet) 
    import qualified Data.IntSet as IntSet 
    import Data.Maybe (isJust) 
    
    step :: Int -> State IntSet (Maybe [Int]) 
    step i = do 
        set <- get 
        if not (IntSet.member i set) 
        then do 
         modify $ IntSet.insert i 
         return $ Just [i, i*10, i*100] 
        else return Nothing 
    
    run xs = filter isJust $ flip evalState IntSet.empty $ mapM step xs 
    
    main = do 
        let result = run [1,2,1,3] 
        print result 
    

    mapMあるか、Scalaの同等であるものは何でも。次に、Stateアクションを実行し、Nothing値を削除します。

    +0

    ありがとうございました! –

    関連する問題