I have recently posted a question about the >>
operator, because even though I have read the LYAH walk the linee section I still have some gaps in my understanding. Below is some code/MVE that I have stumbled upon since which sparkled the following reflections. How come I can get the output that follows the code? will it not be the case that no arguments are provided to the bind operator, and hence that no str
argument can be concatenated as they otherwise would have been using bind as seen in the >>=
definition, and shouldn't the result therefor not be similar to expected result mentioned below:
import Control.Monad
import Data.List
data Value =
NoneVal
| IntVal Int
| ListVal [Value]
deriving (Eq, Show, Read)
type FName = String
data RError = EBadVar String | EBadFun String | EBadArg String
deriving (Eq, Show)
newtype Comp a = Comp {runComp :: [(String, Value)] -> (Either RError a, [String]) }
instance Monad Comp where
return a = Comp( \_ -> (Right a, []))
m >>= f = Comp(\env -> case runComp m env of
(Left e, str) -> (Left e, str)
(Right a, str) -> let (a', str') = runComp (f a) env in (a', str++str'))
-- You shouldn't need to modify these
instance Functor Comp where
fmap = liftM
instance Applicative Comp where
pure = return; (<*>) = ap
showValue :: Value -> String
showValue (IntVal int) = show int
showValue (ListVal values) = "[" ++ intercalate ", " [showValue x| x<-values] ++ "]"
output :: String -> Comp ()
output s = Comp (\_ -> (Right (), [s]))
-- Helper functions for interpreter
apply :: FName -> [Value] -> Comp Value
apply "print" values = output (unwords [showValue x| x<-values]) >> return NoneVal
Output:
ghci> runComp (apply "print" [(IntVal 1), (IntVal 2)]) [("x", (IntVal 4)), ("y", (IntVal 3))]
(Right NoneVal,["1 2"])
Expected output
(Right NoneVal, [])
Furthermore why will extending the bind operator definition with an extra str'
concatenation to this:
(Left e, str) -> (Left e, str)
(Right a, str) -> let (a', str') = runComp (f a) env in (a', str++str'++str'))
and the apply
with another >>
like this:
apply "print" values = output (unwords [showValue x| x<-values]) >> output (unwords [showValue x| x<-values]) >> return NoneVal
, not result in the following:
ghci> runComp (apply "print" [(IntVal 1), (IntVal 2)]) [("x", (IntVal 4)), ("y", (IntVal 3))]
(Right NoneVal,["1 2","1 2","1 2", "1 2"])
rather than the actual:
ghci> runComp (apply "print" [(IntVal 1), (IntVal 2)]) [("x", (IntVal 4)), ("y", (IntVal 3))]
(Right NoneVal,["1 2","1 2","1 2"])
with only 3 inputted elements.