sepp2kの回答では、これはFunctor
とMonad
の違いを示す優れた例です。
Monad
の標準Haskellの定義は、この(簡体字)のようなものになる:
class Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
しかし、これはクラスが定義されていることができる唯一の方法ではありませんが。あなたはfmap
とjoin
の面で>>=
を定義することができることを考えると
class Functor m => Monad m where
return :: a -> m a
join :: m (m a) -> m a
:代替は次のように実行します
(>>=) :: Monad m => m a -> (a -> m b) -> m b
ma >>= f = join (f <$> ma)
私たちは、あなたがしている問題の単純化されたスケッチで、このを見てみましょうに走っている。あなたがIO b
を必要とするので
ma :: IO a
f :: a -> IO b
f <$> ma :: IO (IO b)
は、今あなたが立ち往生している、と
Functor
クラスが
IO (IO b)
からそこにあなたを取得します何も操作を持っていない:あなたがやっていることは、次のように図式化することができます。あなたがしたい場所を取得する唯一の方法は、
Monad
に浸すことであり、
join
操作は、それを解決し、正確に何である:
>>=
の
join (f <$> ma) :: IO b
しかしjoin
/<$>
によって定義、これは同じです:
ma >>= f :: IO a
Control.Monad
ライブラリには、join
(return
と(>>=)
で書かれています)のバージョンが付属しています。それをあなたの関数に入れて、あなたが望む結果を得ることができます。しかし、より良いことは、あなたがしようとしていることが基本的にモナドであることを認識することです。したがって、<$>
は仕事のための適切なツールではありません。ある行動の結果を別の行動に移しています。本質的にはMonad
を使用する必要があります。
私の直感的な感想: 'removeFile'は1つの効果を追加します。最後に1つのエフェクトが必要な場合は、0の効果があるものをフィードしなければなりません。 'lst'はすでに効果があります。最初にそれを削除する必要があります。bind(演算を実行する)を使用して効果を実行し、0効果で値を取得します – nicolas