haskellmonadsalternative-functormonadplus

Haskell function which acts differently depending on the monad type


I'm trying to implement a function which usually puts the first element of a list in a monad, but if the monad is a list it returns the whole list:

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

Should return Just 1, and

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

should return [1,2,3].

Any ideas?


Solution

  • In your particular use-case, you could take advantage of msum:

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

    Then both examples will work:

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

    Note however that Maybe is not exactly MonadPlus, since mplus there is not associative.