
i'm using them right i think because it works, but my understanding is fuzzy. it seems <- is used when you do things like load a file or get arguments from outside or if you are return something from a function these seem to take the form of something other than an internal type like Int or String and have to be 'massaged' into use with things like show or fromSql etc the = is used with let and seems to work for any assignments that are internal. are these assessments correct? -- In friendship, prad ... with you on your journey Towards Freedom http://www.towardsfreedom.com (website) Information, Inspiration, Imagination - truly a site for soaring I's

prad
i'm using them right i think because it works, but my understanding is fuzzy.
it seems <- is used when you do things like load a file or get arguments from outside or if you are return something from a function
these seem to take the form of something other than an internal type like Int or String and have to be 'massaged' into use with things like show or fromSql etc
the = is used with let and seems to work for any assignments that are internal.
are these assessments correct?
No. You are mixing up monadic computations with normal Haskell functions. First of all using "=" you make an equation. You are not saving a result, you are just saying that two things are the same. You use this to define values and functions: (age, sex, location) = (25, Male, "Germany") fourthRoot = sqrt . sqrt You could just as well write '25' whereever your write 'age'. And you could just as well write 'sqrt . sqrt' whereever you write 'fourthRoot', because you defined them to be the same thing. The '<-' syntax on the other hand is unrelated to functions. You use it to give the result of a monadic computation a name. Example: line <- getLine getLine is a value of type IO String. Notice that getLine is /not/ a function. It's simply a value. But it's a monadic one, because IO is a monad, so whenever you use 'do' notation, you can refer to the result of it by using the '<-' syntax. Let's go deeper into it: content <- readFile "blah.txt" Now readFile is a function. It's of the following type: readFile :: FilePath -> IO String Because it is a function you need to apply it to a value of type FilePath first, yielding, guess what, a simple value. That value is of type IO String, so it's a monadic value, an IO computation. That computation, when run, has a result. And by using '<-' you give this result the name 'content', so you can refer to it. Again, 'content' is /not/ the result of the readFile function, because that result is a computation of type IO String. Let's see the difference: let readBlahTxt = readFile "blah.txt" content <- readBlahTxt This should show the difference more clearly. Greets, Ertugrul -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://ertes.de/

Not really...
Remember <- is part of the do notation. You use it within monads when using
do, and never outside of them :) Well... list comps as well, but it's much
of a muchness.
On 11 August 2010 22:12, prad
i'm using them right i think because it works, but my understanding is fuzzy.
it seems <- is used when you do things like load a file or get arguments from outside or if you are return something from a function
these seem to take the form of something other than an internal type like Int or String and have to be 'massaged' into use with things like show or fromSql etc
the = is used with let and seems to work for any assignments that are internal.
are these assessments correct?
-- In friendship, prad
... with you on your journey Towards Freedom http://www.towardsfreedom.com (website) Information, Inspiration, Imagination - truly a site for soaring I's _______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

To really understand the difference between = and <- you need to understand the syntactic sugar that the do notation provides. Given the following: myExample :: Int -> IO Int myExample num = return num You could write the following: main = do theNum <- myExample 42 putStrLn (show theNum) This is exactly the same as writing the following: main = (myExample 42) >>= (\theNum -> putStrLn (show theNum)) The type of >>= is: m a -> (a -> m b) -> m b Remember that in most cases, once something is "inside" of a monad (IO in this case), it's very difficult, impossible, to get it out again. What >>= provides, is a way of taking a value out of a monad, using some function on it that returns a new value inside that same monad, and then returning that. For example, once the types get bound, the
= in the above example has type:
IO Int -> (Int -> IO ()) -> IO ()
The m has been bound to IO, a is bound to Int, and b has been bound to
(). This is because the type of putStrLn is String -> IO (). The do
syntax just adds a convenient abstraction so that you don't have to
construct complex chains of >>= and >> operations by hand. In our
limited example this is fairly trivial, but consider something like:
main = do
something <- foo
blah <- bar something
moreblah <- baz something blah
putStrLn moreblah
putStrLn "really long chain now"
which would be translated to:
main = foo >>= (\something -> bar something >>= (\blah -> baz
something blah >>= (\moreblah -> putStrLn moreblah >> (putStrLn
"really long chain now"))))
Conceptually you can think of (<-) as having type:
a <- IO a
although since (<-) isn't really an op (it's syntactic sugar that's
only valid inside the do notation, it doesn't exist after you remove
the sugar) it of course doesn't really have a type. This also why you
can't just use (=) inside of do notation, and instead have to use let,
you need to escape out of the sugar before you can use it. For an
example of why this is, consider the following:
main = do
something = foo
putStrLn something
which would be translated into:
main = something = foo >>= (putStrLn something)
which of course doesn't make any sense at all.
-R. Kyle Murphy
--
Curiosity was framed, Ignorance killed the cat.
On Wed, Aug 11, 2010 at 16:12, prad
i'm using them right i think because it works, but my understanding is fuzzy.
it seems <- is used when you do things like load a file or get arguments from outside or if you are return something from a function
these seem to take the form of something other than an internal type like Int or String and have to be 'massaged' into use with things like show or fromSql etc
the = is used with let and seems to work for any assignments that are internal.
are these assessments correct?
-- In friendship, prad
... with you on your journey Towards Freedom http://www.towardsfreedom.com (website) Information, Inspiration, Imagination - truly a site for soaring I's _______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

Kyle Murphy
Remember that in most cases, once something is "inside" of a monad (IO in this case), it's very difficult, impossible, to get it out again.
I think, this is very misleading. You never get "out of a monad", you get "into" it, and you can do that whenever you want. Remember that the monadic world is inside of the pure world, not the pure world inside of the monadic world. In fact, the monadic world is part of it. The name bound by '<-' is something you can refer to in the pure world. There is nothing difficult about using the result of a monadic computation in the pure world. Just give it a name and refer to it, and that's it.
The do syntax just adds a convenient abstraction so that you don't have to construct complex chains of >>= and >> operations by hand. In our limited example this is fairly trivial, but consider something like:
main = do something <- foo blah <- bar something moreblah <- baz something blah putStrLn moreblah putStrLn "really long chain now"
Pretty straightforward: main = foo >>= \something -> bar something >>= \blah -> baz something blah >>= \moreblah -> putStrLn moreblah >> putStrLn "really long chain now"
which would be translated to:
main = foo >>= (\something -> bar something >>= (\blah -> baz something blah >>= (\moreblah -> putStrLn moreblah >> (putStrLn "really long chain now"))))
You could just as well write: main = do { something <- foo; blah <- bar something; moreblah <- baz something blah; putStrLn moreblah; putStrLn "really long chain now" } You are complicating things artifically. For example there is no reason to have all those parentheses, because (>>=) is associative by definition. The do-notation doesn't make nasty things nice. It makes nice things nicer. Don't be afraid to use raw monadic combinators, because sometimes they are much better: main = getArgs >>= mapM_ (readFile >=> putStr) Much more concise than: main = do files <- getArgs forM_ files $ \file -> do content <- readFile file putStr content Greets, Ertugrul -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://ertes.de/

Ertugrul Soeylemez
wrote: I think, this is very misleading. You never get "out of a monad", you get "into" it, and you can do that whenever you want. Remember that the monadic world is inside of the pure world, not the pure world inside of the monadic world. In fact, the monadic world is part of it.
Not really, it depends on how you look at things. If you want to use the result of something that returns an IO Monad inside of a pure function, you really can't do that without in turn making that function impure (that is, putting it inside of the IO Monad as well), so to one way of looking at it, values (and functions) exist inside Monads and with few exceptions are impossible to remove from those Monads. You can always embed your pure function inside a non-pure function, but the opposite is not true. Most of the monads do provide functions like fromJust, and unsafePerformIO (never use this, seriously) that can allow you to escape from the monad, but doing so is often risky. The monadic world as you put it, really isn't inside of the pure world except in theory. From a practical standpoint everything exists inside the IO monad at some level, it's just lower level functions that are pure (that is, functions can be pure, but at some point they MUST be called from the IO monad). I know theoretically monads are built on top of pure math, but to me the difference between monads as a concept and monads as implemented in Haskell, is similar to the difference between proving a program to be correct, and actually running it.
You are complicating things artifically. For example there is no reason to have all those parentheses, because (>>=) is associative by definition.
The do-notation doesn't make nasty things nice. It makes nice things nicer. Don't be afraid to use raw monadic combinators, because sometimes they are much better:
The example I provided was still relatively simple, and apparently
didn't need all the parentheses, but I wasn't going to bet on it, and
had I used other operators, say some provided by a module, who knows
what kinds of associativity would be involved. I generally always use
parentheses around lambdas if for no other reason than to make it
easier to see what their scope is.
I never said the monad operators were nasty, or that the do notation
was nicer, just that often it is more convenient. There are instances
where I find it simpler and easier to read an expression using the
monad operators rather than do notation, and vice versa, so it really
depends on the particular instance. Sometimes I even find it most
readable to combine the two into something like:
foobar = do
baz <- foo 42
bar baz >>= putStrLn . show . xyzzy baz
Once again, this is not supposed to be a specific example, just a
conceptual one vaguely representative of the form of actual ones I've
run across before.
-R. Kyle Murphy
--
Curiosity was framed, Ignorance killed the cat.
On Fri, Aug 13, 2010 at 20:06, Ertugrul Soeylemez
Kyle Murphy
wrote: Remember that in most cases, once something is "inside" of a monad (IO in this case), it's very difficult, impossible, to get it out again.
I think, this is very misleading. You never get "out of a monad", you get "into" it, and you can do that whenever you want. Remember that the monadic world is inside of the pure world, not the pure world inside of the monadic world. In fact, the monadic world is part of it.
The name bound by '<-' is something you can refer to in the pure world. There is nothing difficult about using the result of a monadic computation in the pure world. Just give it a name and refer to it, and that's it.
The do syntax just adds a convenient abstraction so that you don't have to construct complex chains of >>= and >> operations by hand. In our limited example this is fairly trivial, but consider something like:
main = do something <- foo blah <- bar something moreblah <- baz something blah putStrLn moreblah putStrLn "really long chain now"
Pretty straightforward:
main = foo >>= \something -> bar something >>= \blah -> baz something blah >>= \moreblah -> putStrLn moreblah >> putStrLn "really long chain now"
which would be translated to:
main = foo >>= (\something -> bar something >>= (\blah -> baz something blah >>= (\moreblah -> putStrLn moreblah >> (putStrLn "really long chain now"))))
You could just as well write:
main = do { something <- foo; blah <- bar something; moreblah <- baz something blah; putStrLn moreblah; putStrLn "really long chain now" }
You are complicating things artifically. For example there is no reason to have all those parentheses, because (>>=) is associative by definition.
The do-notation doesn't make nasty things nice. It makes nice things nicer. Don't be afraid to use raw monadic combinators, because sometimes they are much better:
main = getArgs >>= mapM_ (readFile >=> putStr)
Much more concise than:
main = do files <- getArgs forM_ files $ \file -> do content <- readFile file putStr content
Greets, Ertugrul
-- nightmare = unsafePerformIO (getWrongWife >>= sex) http://ertes.de/
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

Kyle Murphy
Ertugrul Soeylemez
wrote: I think, this is very misleading. You never get "out of a monad", you get "into" it, and you can do that whenever you want. Remember that the monadic world is inside of the pure world, not the pure world inside of the monadic world. In fact, the monadic world is part of it.
Not really, it depends on how you look at things. If you want to use the result of something that returns an IO Monad inside of a pure function, you really can't do that without in turn making that function impure (that is, putting it inside of the IO Monad as well), so to one way of looking at it, values (and functions) exist inside Monads and with few exceptions are impossible to remove from those Monads. You can always embed your pure function inside a non-pure function, but the opposite is not true. Most of the monads do provide functions like fromJust, and unsafePerformIO (never use this, seriously) that can allow you to escape from the monad, but doing so is often risky. The monadic world as you put it, really isn't inside of the pure world except in theory. From a practical standpoint everything exists inside the IO monad at some level, it's just lower level functions that are pure (that is, functions can be pure, but at some point they MUST be called from the IO monad). I know theoretically monads are built on top of pure math, but to me the difference between monads as a concept and monads as implemented in Haskell, is similar to the difference between proving a program to be correct, and actually running it.
I don't agree. The pure world is the evaluation world -- the world, where you write your program. The impure world is the execution world, where your program gets run. You cannot pull a value generated by execution into the evaluation world, because at that point there is no execution. That's what people refer to as "escaping from IO". Escaping from IO doesn't make sense in Haskell, hence it's an unsafe thing to do using hacks like 'unsafePerformIO'. However, you can give those values a name, either by using (>>=) or by using '<-' in do-notation. This name can be referred to in the evaluation world. The monadic world is part of the pure world, because monads still belong to the evaluation world. The actual execution of the program is independent and none is inside of the other. There are lots of ways to pass results of IO actions to pure functions. Trying to use a value from execution in evaluation is a completely wrong line of thought. It doesn't make sense, and the types don't fit anyway. If you need random numbers, pass a random number generator or the random numbers needed. You can use state and reader monads to make this passing implicit, if you wish. Greets, Ertugrul -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://ertes.de/
participants (4)
-
Benjamin Edwards
-
Ertugrul Soeylemez
-
Kyle Murphy
-
prad