2017-02-02 6 views
1

通常、リストの最初の要素をモナドに入れる関数を実装しようとしていますが、モナドがリストであればリスト全体を返します:モナドの型によって異なる動作をするHaskell関数

putInMonad :: MonadPlus m => [a] -> m a 
putInMonad (s:sx) = return s 
putInMonad _ = mzero 
putInMonad [1,2,3] :: Maybe Int 

Just 1を返す必要があります、と

putInMonad [1,2,3] :: [] Int 

[1,2,3]を返す必要があります。

アイデア?関数がFooインスタンスは関数が呼び出されたときに使用されるかを知ることができないので

+0

下位モナドとして '[[]] Int'を使うことができます。 –

+0

@WillemVanOnsemいいえ、式 'return s'に' sx'に関する情報が含まれていないためです。単に具体的な戻り値の型を指定してもそれは役に立ちません。 – chepner

+0

@chepner:そう、私はそれがその特定のモナドに対して異なって振る舞いません。他の方法で問題を解決するというアイデアしかありませんでした。アイテムのリストではなくリストのリストを与えます。 –

答えて

5

% putInMonad [1,2,3,4] :: Maybe Int 
Just 1 
% putInMonad [1,2,3,4] :: [Int] 
[1,2,3,4] 

注しかしMaybemplusいるので、正確にMonadPlusではないこと連想ではありません。

+4

'MonadPlus'に関する不安や論争は、' MonadPlus'制約がOPに対して厳しい要件でない場合、 'Alternative'と' asum'に切り替えることで回避できます。 – duplode

1

は一般的に、あなたはそれがreturn sまたはreturn (s:sx)を返すように決定するための根拠を持っていないことを意味、これを行うことはできません。

FooMonadPlusの場合、この特定のケースでは、回避策があります(@marc's answer参照)。

putInMonad :: MonadPlus m => [a] -> m a 
putInMonad x = msum $ map return x 

その後、両方の例は動作します:あなたの特定のユースケースでは、あなたがmsumの利点を取ることができる

+0

私が技術的に正しいのか、間違っているのかを投票するのを待っています。 – chepner

+0

あなたは技術的に正しいわけではありませんが、問題のクラスが 'MonadPlus'なので、単にmarcの答えに示されている回避策を提供しているからです。これが一般的なケースでは不可能であることは、まだ価値があることです。私はあなたの答えを編集して、この微妙さを明確にし、そして/または対照のためにmarcの答えを指摘することを提案します。 – duplode

関連する問題