How to extract value from monadic action

前端 未结 8 2154

Is there a built-in function with signature :: (Monad m) => m a -> a ?

Hoogle tells that there is no such function.

Can you explain why?<

相关标签:
8条回答
  • 2020-11-27 05:37

    A monad only supplies two functions:

    return :: Monad m => a -> m a
    (>>=) :: Monad m => m a -> (a -> m b) -> m b
    

    Both of these return something of type m a, so there is no way to combine these in any way to get a function of type Monad m => m a -> a. To do that, you'll need more than these two functions, so you need to know more about m than that it's a monad.

    For example, the Identity monad has runIdentity :: Identity a -> a, and several monads have similar functions, but there is no way to provide it generically. In fact, the inability to "escape" from the monad is essential for monads like IO.

    0 讨论(0)
  • 2020-11-27 05:37

    Is there a build-in function with signature :: (Monad m) => m a -> a ?

    If Hoogle says there isn't...then there probably isn't, assuming your definition of "built in" is "in the base libraries".

    Hoogle tells that there is no such function. Can you explain why?

    That's easy, because Hoogle didn't find any function in the base libraries that matches that type signature!

    More seriously, I suppose you were asking for the monadic explanation. The issues are safety and meaning. (See also my previous thoughts on magicMonadUnwrap :: Monad m => m a -> a)

    Suppose I tell you I have a value which has the type [Int]. Since we know that [] is a monad, this is similar to telling you I have a value which has the type Monad m => m Int. So let's suppose you want to get the Int out of that [Int]. Well, which Int do you want? The first one? The last one? What if the value I told you about is actually an empty list? In that case, there isn't even an Int to give you! So for lists, it is unsafe to try and extract a single value willy-nilly like that. Even when it is safe (a non-empty list), you need a list-specific function (for example, head) to clarify what you mean by desiring f :: [Int] -> Int. Hopefully you can intuit from here that the meaning of Monad m => m a -> a is simply not well defined. It could hold multiple meanings for the same monad, or it could mean absolutely nothing at all for some monads, and sometimes, it's just simply not safe.

    0 讨论(0)
  • 2020-11-27 05:39

    There is probably a better answer than this, but one way to see why you cannot have a type (Monad m) => m a -> a is to consider a null monad:

    data Null a = Null
    
    instance Monad Null where
        return a = Null
        ma >>= f = Null
    

    Now (Monad m) => m a -> a means Null a -> a, ie getting something out of nothing. You can't do that.

    0 讨论(0)
  • 2020-11-27 05:40

    This doesn't exist because Monad is a pattern for composition, not a pattern for decomposition. You can always put more pieces together with the interface it defines. It doesn't say a thing about taking anything apart.

    Asking why you can't take something out is like asking why Java's Iterator interface doesn't contain a method for adding elements to what it's iterating over. It's just not what the Iterator interface is for.

    And your arguments about specific types having a kind of extract function follows in the exact same way. Some particular implementation of Iterator might have an add function. But since it's not what Iterators are for, the presence that method on some particular instance is irrelevant.

    And the presence of fromJust is just as irrelevant. It's not part of the behavior Monad is intended to describe. Others have given lots of examples of types where there is no value for extract to work on. But those types still support the intended semantics of Monad. This is important. It means that Monad is a more general interface than you are giving it credit for.

    0 讨论(0)
  • 2020-11-27 05:47

    Well, technicaly there is unsafePerformIO for the IO monad.

    But, as the name itself suggests, this function is evil and you should only use it if you really know what you are doing (and if you have to ask wether you know or not then you don't)

    0 讨论(0)
  • 2020-11-27 05:49

    Because it may make no sense (actually, does make no sense in many instances).

    For example, I might define a Parser Monad like this:

    data Parser a = Parser (String ->[(a, String)])
    

    Now there is absolutely no sensible default way to get a String out of a Parser String. Actually, there is no way at all to get a String out of this with just the Monad.

    0 讨论(0)
提交回复
热议问题