Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

haskell - What's so special about 'return' keyword

When I seemed to understand what return is for in Haskell, I tried to play with different alternatives and it seems that return not only can be used anywhere in the monad chain, but also can be excluded completely

*Main> Just 9 >>= y -> (Just y) >>= x -> return x
Just 9

*Main> Just 9 >>= y -> (return y) >>= x -> (Just y)
Just 9

*Main> Just 9 >>= y -> (Just y) >>= x -> (Just x)
Just 9 

Even if I omit return in my own instancing, I only get warning...

data MaybeG a = NothingG | JustG a deriving Show 
instance Monad MaybeG where  
    --    return x = JustG x  
        NothingG >>= f = NothingG  
        JustG x >>= f  = f x  
        fail _ = NothingG  

Monad.hs:3:10:
    Warning: No explicit method nor default method for `return'
    In the instance declaration for `Monad MaybeG'

and I still can use the monad

*Main> JustG 9 >>= y -> (JustG 11) >>= x -> (JustG y)
JustG 9

*Main> JustG 9 >>= y -> (NothingG) >>= x -> (JustG y)
NothingG

So what's so special about the return keyword? Is this about more complex cases where I can not omit it? Or because this is the "right" way to do things even if they can be done differently?

UPDATE: .. or another alternative, I could define my own monadic value constructor

finallyMyLastStepG :: Int -> MaybeG Int
finallyMyLastStepG a = JustG a  

and produce another variant of the same chain (with the same result)

*Main> JustG 9 >>= y -> (JustG 11) >>= x -> (finallyMyLastStepG y)
JustG 9
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

So what's so special about the return keyword?

Firstly, return is not a keyword in Haskell. It is an overloaded function.

Its type is given by:

class  Monad m  where
    -- | Sequentially compose two actions, passing any value produced
    -- by the first as an argument to the second.
    (>>=)       :: m a -> (a -> m b) -> m b

    -- | Inject a value into the monadic type.
    return      :: a -> m a

So you see that return is a function that given a value of type a, returns a new value of type m a, where m is some type that is an instance of Monad. Such types include:

  • Monad []
  • Monad I0
  • Monad Maybe
  • Monad STM
  • Monad ((->) r)
  • Monad (Either e)
  • Monad (ST s)

and many more besides. Instances of 'Monad' should satisfy the following laws:

> return a >>= k  ==  k a
> m >>= return  ==  m
> m >>= (x -> k x >>= h)  ==  (m >>= k) >>= h

The implementation of a function a -> m a is pretty easy to guess. Here's the definition for the most common monads:

Lists:

 return x = [x]

Maybe

 return x = Just x

So you see that the return is an overloaded function that "lifts" a value into a monadic wrapper. You can thus use it anywhere you can use its definition. E.g.

Prelude> 1 : return 2
[1,2]

or in the do notion (useful when chaining expressions).

> do v <- return 7 ; return v :: Maybe Int
Just 7

The real reason to use a monadic return is when composing multiple values in some monad:

Prelude> do x <- return 1 ; y <- return 2 ; return (x + y) :: Maybe Int
Just 3
Prelude> do x <- Nothing  ; y <- return 2 ; return y
Nothing

In the last statement you see how the chain short-circuited once it hit a zero value for the given monad. In this case Nothing.

Summary: return is an overloaded function that lifts a value into a monadic wrapper. You use it when you need to lift values. It is not a control-flow keyword, as it is in imperative languages.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...