Reputation: 5073
I have written a my monad representing some computations. Now, I would like to define how the computation should be sequenced
. So, I am going to define >>=
. But, control of flow forced me to focus on conrete type of a
. I mean:
m >>= f =
a <- m
case a of
(ParticularParameterA) -> doSomething
..........
Is it proper solution? I mean: I have no experience in functional programming so I am not sure is it ok to do it or not. How to do it better?
Upvotes: 0
Views: 97
Reputation: 1134
It is possible that your situation falls into the simple pattern where your monad if of the form:
newtype MyMonad a = MyMonad { run :: State -> (a, State) }
where State
is a data type you have designed yourself. The point is you probably have a function:
run :: MyMonad a -> State -> (a, State)
and you probably need to use this function when implementing (>>=):
m >>= f = MyMonad(\state -> let (x, newState) = run m state in
case x of
(ParticularParameterA) -> doSomething
..........
Now if f::a -> MyMonad b
your \state -> ...
function must return a (b, State)
, so you probably want to use run (f x) newState
somewhere in your code.
if your monadic type is of the form:
newtype MyMonad a = MyMonad { run :: State -> Maybe (a, State) }
newtype MyMonad a = MyMonad { run :: State -> Either String (a, State) }
then you still use the run
function, e.g.
m >>= f = MyMonad (\state -> case run m state of
Just (x, newState) -> run (f x) newState
Nothing -> Nothing)
Upvotes: 1
Reputation: 153182
The case
statement and syntax errors notwithstanding, this definition is indeed clearly nonsensical, as binding from within a do-block gets translated to a use of >>=
. So your existing code has defined m >>= f = m >>= \a -> ...
, which is both an infinite loop and a space leak in one.
Upvotes: 2