The code I am looking at contains this top level function:
starman :: String -> Int -> IO ()
starman word n = turn word ['-' | x <- word] n
I can see that this is a function that takes 2 arguments and then calls the turn function that looks like this:
turn :: String -> String -> Int -> IO ()
turn word display n =
do if n==0
then putStrLn "You lose"
else if word==display
then putStrLn "You win!"
else mkguess word display n
What I don't understand is what this means:
word ['-' | x <- word]
The full line is:
starman word n = turn word ['-' | x <- word] n
turn
is called with three parameters:
word
['-' | x <- word]
n
The middle one is the one you're having trouble with. It can be read as: "a hyphen for each character in word."
So ['-' | x <- "hello"]
['-' | x <- "hello"]
is "-----"
.
This construct is known as list comprehension .
EDIT
The list comprehension does the same thing as this, which is perhaps clearer in intent?
replicate (length word) '-'
word
is the first argument to the turn
function.
['-' | x <- word]
['-' | x <- word]
is the second argument and it's a list containing one '-'
for each letter x
in word
. The fact that we give each letter the name x
accomplishes nothing though, as we never refer to it, so we might as well write ['-' | _ <- word]
['-' | _ <- word]
.
This syntax is known as a list comprehension and is meant to look similar to set notation.
Actually, in the following expression
turn word ['-' | x <- word] n
there a function ( turn
) call, with three arguments: word
, ['-' | x <- word]
['-' | x <- word]
, and n
. So ['-' | x <- word]
['-' | x <- word]
is independent of word
.
Now, what is the meaning of ['-' | x <- word]
['-' | x <- word]
? This is a list comprehension, so it's an expression that constructs a list. In order to understand this, you have to remember that strings in haskell are just lists of characters. So word
is a list. The x <- word
means: take each element of the list word
, call it that element x
and then for each such element, evaluate the expression '-'
and collect all those values into a list. In this case, the expression '-'
does not reference x
, so it will always evaluate to '-'
. So in other words, we are taking the list of characters word
and creating a list where each element-character is replaces by '-'
.
Here are some equivalent ways to do the same thing:
['-' | _ <- word] -- use the anonymous variable, we don't need the element
map (\_ -> '-') word
map (const '-') word
'-' <$ word -- my favorite one!
replicate (length word) '-' -- the least preferrable way
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.