2017-04-15 11 views
4

私はa -> IO (Maybe b)型の関数を持っていて、それをIO (Maybe a)に適用してIO (Maybe b)を与えたいと思います。私はそれを行う関数を書いた:IO内部の値に関数を適用する

ioMaybeApply :: (a -> IO (Maybe b)) -> IO (Maybe a) -> IO (Maybe b) 
ioMaybeApply f ioMaybeA = do 
    maybeA <- ioMaybeA 
    maybe (return Nothing) f maybeA 

それを行うための標準的なハスケル関数はありますか?私はHoogleで検索しようとしましたが、何も見つかりませんでした。そうでない場合は、私の実装は良いですか、それとも簡単にできますか?

+0

しかし、おそらく:: b - >(a - > b) - > bは 'IO'モナドではありませんか? –

+1

@WillemVanOnsem私のコードでは、 'maybe'は' return Nothing'( 'IO(Maybe b)'型)または 'f'(' IO(Maybe b) ')の戻り値のいずれかを返します。 –

答えて

6

これはMaybeT monad transformerを通じて達成することができます:

GHCi> import Control.Monad.Trans.Maybe 
GHCi> :t \f m -> runMaybeT (MaybeT m >>= MaybeT . f) 
\f m -> runMaybeT (MaybeT m >>= MaybeT . f) 
    :: Monad m => (a1 -> m (Maybe a)) -> m (Maybe a1) -> m (Maybe a) 
import Control.Monad.Trans.Maybe 

-- Making it look like your definition, for the sake of comparison. 
ioMaybeApply :: (a -> IO (Maybe b)) -> IO (Maybe a) -> IO (Maybe b) 
ioMaybeApply f ioMaybeA = runMaybeT $ do 
    a <- MaybeT ioMaybeA 
    MaybeT (f a) 

あなたが複数の場所でこのパターンを使用している場合、それはおそらくa -> MaybeT IO bにごa -> IO (Maybe b)の機能を変更することが報われる - あなたは特殊用途の機能の代わりに(>>=)および/またはシームレスなブロックを使用することができます。一方、これがちょうど一回限りのものであれば、MaybeTを使用することは過度のものであると合理的に考えるかもしれません。その場合、実装は完璧です。

(必ずしも何かにはなりません営巣2つのモナドとして、FunctorApplicativeインスタンスを持つComposeと呼ばれる、ネストされたファンクタのための汎用的なラッパーがありながら、それはMonadインスタンスを持っていないことを言及する価値があります法律であるMonadインスタンスを指定することができますが、通常は、動作する各組み合わせに合わせてモナド変圧器を使用しています)

+0

'MaybeT'が過剰である場合:'(fmap。fmap) 'を使用することがあります。 –

+0

@JeremyList Yup。 (他の読者のためのメモ:この場合、MaybeT IO(または 'IO Compose IO Maybe')のための' fmap'の手書き同等の量になります.Michałの 'ioMaybeApply'は手書きの' (>> =) '' MaybeT IO'のために)。 – duplode

関連する問題