我正在查看的代码包含这个顶级函数:
starman :: String -> Int -> IO ()
starman word n = turn word ['-' | x <- word] n
我可以看到这是一个带有2个参数的函数,然后调用如下所示的turn函数:
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
我不明白的是这意味着什么:
word ['-' | x <- word]
答案 0 :(得分:5)
完整的一行是:
starman word n = turn word ['-' | x <- word] n
使用三个参数调用 turn
:
word
['-' | x <- word]
n
中间的那个是你遇到麻烦的。它可以理解为:“单词中每个字符的连字符。”
所以['-' | x <- "hello"]
是"-----"
。
此构造称为list comprehension。
修改强>
列表理解与此相同,这在意图中可能更清晰吗?
replicate (length word) '-'
答案 1 :(得分:2)
word
是turn
函数的第一个参数。
['-' | x <- word]
是第二个参数,它是'-'
中每个字母x
包含一个word
的列表。我们给每个字母命名x
的事实虽然没有实现,但我们从不提及它,所以我们不妨写['-' | _ <- word]
。
此语法称为列表推导,其外观与set notation类似。
答案 2 :(得分:1)
实际上,在以下表达式中
turn word ['-' | x <- word] n
有一个函数(turn
)调用,有三个参数:word
,['-' | x <- word]
和n
。因此['-' | x <- word]
独立于word
。
现在,['-' | x <- word]
的含义是什么?这是一个列表理解,因此它是一个构造列表的表达式。为了理解这一点,你必须记住haskell中的字符串只是字符列表。所以word
是一个列表。 x <- word
表示:获取列表word
的每个元素,将其称为元素x
,然后对于每个此类元素,评估表达式'-'
并将所有这些值收集到一个列表。在这种情况下,表达式'-'
不会引用x
,因此它将始终评估为'-'
。换句话说,我们正在获取字符列表word
并创建一个列表,其中每个元素字符由'-'
替换。
以下是一些做同样事情的等效方法:
['-' | _ <- 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