0

I am trying to get a better grasp of the do statement and it's syntacs. So far I have come to understand from written material that x <- statement evaluates the statement-expression and assign it to x, whereas the let x = statement gives the statement a new name, x, without evaluating it first.

If that is the case how come this works:

fmap_int f g = 
   do 
      toInt <- getLine
      let x = read toInt :: Integer      
      let y = fmap f g x       
      return y


when this doesn't work:

fmap_int2 f g = 
   do 
      toInt <- getLine
      let x = read toInt :: Integer      
      y <- fmap f g x 
      return y

Piskator
  • 605
  • 1
  • 9
  • `fmap f g x` looks fishy, this does something very different from what you probably intended. `fmap` only takes two arguments (though as a consequence of Haskell's currying it actually typechecks also with three, but I recommend you forget about this fact until you have a really firm grasp with monads). Also, you should make it a habit to add type signatures; amongst other advantages this prevents the compiler from typechecking your code by instantiating type variables in a way that is bogus in practice. – leftaroundabout Aug 16 '22 at 09:47
  • 1
    The explanation is phrased in misleading and inaccurate terms. Which written material are you using? `x <- statement` desugars to `statement >>= \x -> (the rest of the block)`. `let x = statement` desugars to simply `let x = statement in (the rest of the block)`. These are different things with different types. It is important to understand what `>>=` does. – n. m. could be an AI Aug 16 '22 at 09:54
  • @n.1.8e9-where's-my-sharem. could you elaborate a bit more, I am using https://en.wikibooks.org/wiki/Haskell/do_notation but I also think I read the stackoverflow discussion suggested by Guru Stron – Piskator Aug 16 '22 at 09:59
  • 3
    Specifically "evaluate the statement" is misleading. I would say "run the monadic computation". The word "evaluate" is applicable to any term so it's better not to use it here. It is important to understand that "statement" in `x<-statement` is a monadic computation (and this fact is the only basis for calling it a "statement"). OTOH the "statement" in `let x = statement` is any old expression. Calling it a "statement" is wrong and misleading. There is nothing to run. These two entities are completely different. – n. m. could be an AI Aug 16 '22 at 10:18
  • @leftaroundabout how do I type check the 'let'-parts of a do notation in order to do what you recommend. In other words what would a fully type-checkec version of the above code look like, so that I could see the difference in types of the two 'entities' as the other commenters are talking about. – Piskator Aug 16 '22 at 10:28
  • You can always add local signatures to expressions (as you did with `read toInt :: Integer`), including expressions to the right of `<-`. Also, and more importantly, global signatures to definitions (`fmap_int2 :: ...` right before the definition). – leftaroundabout Aug 16 '22 at 12:42

0 Answers0