user266003
user266003

Reputation:

Not using a variable for <-

This code obviously works

import Data.Char

main = do
  content <- readFile "in.txt"
  writeFile "out.txt" (map toUpper content)

Why this one doesn't?

import Data.Char

main = do
  writeFile "out.txt" (map toUpper $ <- readFile "in.txt")

Upvotes: 8

Views: 441

Answers (4)

bheklilr
bheklilr

Reputation: 54068

The <- "extracts" a value from a monadic container. IO is a monad, and so it can be used to extract a value from an IO action. However, the syntax of Haskell says that you must bind it to a name before using it. In actuality, the <- isn't an operator at all, but syntactic sugar for the >>= operator (pronounced "bind"). So when you write

main = do
    contents <- readFile "in.txt"
    writeFile "out.txt" (map toUpper contents)

It gets turned into

main = readFile "in.txt" >>= (\contents -> writeFile "out.txt" (map toUpper contents))

Now, imagine if you had a lot more statements in main. Maybe you extracted several values with <-, and some of the expressions used more than one of those values at a time. You could definitely write the "desugared" version, but it would start getting very, very difficult. The do-notation simplifies this and makes the compiler take care of it for you.

Upvotes: 6

n. m. could be an AI
n. m. could be an AI

Reputation: 120049

First, <- is not an operator. It's a special syntax element that requires a pattern on the left side.

Second, if it were an infix operator, $ <- would not work, as you cannot have two infix operators next to each other.

Upvotes: 16

Fred Foo
Fred Foo

Reputation: 363787

Because this is not how <- is defined. It translates to

readFile "in.txt" >>= \content ->
writeFile "out.txt" (map toUpper content)

You could use =<< instead:

writeFile "out.txt" . map toUpper =<< readFile "in.txt"

Upvotes: 16

Ilya Rezvov
Ilya Rezvov

Reputation: 944

you can to write it as follows

readFile "in.txt" >>= writeFile "out.txt" . map toUpper

Upvotes: 3

Related Questions