I am defining an instance of a monad as follows:
data Something = Something a
instance Monad Something where
return a = Something a --Wraps a in 'Something', correct?
m >>= f = do
var <- m
return $ f var --I want this to pass var to f, then wrap the result
--back up in the 'Something' monad with the return I
--Just defined
The questions are ->
1: Are there any glaring errors/misconceptions with what I am doing?
2: Will Haskell know to call the return I have defined above from m >>= f
3: If I for some reason define another function
f :: Something a -> Something b
f x = do
var <- x
return $ doMagicTo x
Will return call the return I defined in the monad instance and wrap x in Something?
There are a few big problems here.
First, a
Monadinstance must have kind* -> *. That means they need at least one type variable, where yourSomethingdoesn’t have any. For comparison:See how each of
Maybe,IO, andEither Stringneed a type parameter before you can use them? WithSomething, there’s no place for the type parameter to fill in. So you need to change your definition to:The second big problem is that the
>>=in your Monad instance is wrong. You generally can’t use do-notation because that just calls theMonadfunctionsreturnand>>=. So you have to write it out without any monad functions, either do-notation or calling>>=orreturn.The definition of
>>=is simpler than you expected. Unwrappingmis easy because you just need to pattern-match on theSomethingconstructor. Alsof :: a -> m b, so you don’t need to worry about wrapping it up again, becausefdoes that for you.While there’s no way to unwrap a monad in general, very many specific monads can be unwrapped.
Be aware that there’s nothing syntactically wrong with using do-notation or
>>=in the monad instance declaration. The problem is that>>=is defined recursively so the program goes into an endless loop when you try to use it.(N.B.
Somethingas defined here is the Identity monad)For your third question, yes the
returnfunction defined in the Monad instance is the one that will be called. Type classes are dispatched by type, and as you’ve specified the type must beSomething bthe compiler will automatically use the Monad instance forSomething. (I think you meant the last line to bedoMagicTo var).