如果否则在haskell中使用列表理解

时间:2014-05-01 09:53:01

标签: haskell list-comprehension

我正在编写一个代码,其中包含if else with list comprehension是否允许,如果没有,我怎么能写这段代码?

valid :: [(String, Int)]-> [String]-> [(String, Int)]
vaild dict words = [if checks word dict
                    then (word, scores word)|word <- words ]

其中check给出bool值

2 个答案:

答案 0 :(得分:8)

在Haskell中,一切都有类型吗?所以if checks word dict then ...有一个特定的类型, 在这种情况下(String, Int)。想象一下,如果checks word dict是假的,我们仍然需要生成(String, Int)类型的东西,那么我们究竟能做什么呢?

为了避免这个明显的泥潭,Haskell 始终需要 else子句。将if then else视为C&#39 {s} foo ? bar : baz(三元运算符)更为准确。

然而,在列表理解中,这是一个很好的解决方案。你可以将谓词放在理解体中,以防止&#34;守护&#34;什么到达左侧

[(word, scores word) | word <- words, checks word dict]

这基本上是通过选择words中的每个单词然后检查checks word dict,如果返回false,我们&#34;跳过&#34;这个元素。

实际上是monad和MonadPlus之间的联系,但是我没有提到这个,因为我觉得这只会让你感到困惑:)这对你来说没问题。把它视为一点点魔力。

答案 1 :(得分:2)

我不明白为什么你被投票了。正如您对问题的评论所述,您可能需要这样的内容:

valid :: [(String, Int)]-> [String]-> [(String, Int)]
valid dict words = [(word, scores word) | word <- words, checks word dict]

这与你在Python中实现它的方式非常相似。

或者,您可以使用&#34; do&#34;符号:

import Control.Monad (guard)

valid :: [(String, Int)]-> [String]-> [(String, Int)]
valid dict words = do 
    word <- words
    guard (checks word dict)
    return (word, scores word)

或者,如果您根本不想使用列表推导,那么这样的事情会起作用:

import Control.Arrow

valid :: [(String, Int)]-> [String]-> [(String, Int)]
valid dict words = map (id &&& scores) $ filter (\word -> checks word dict) words

可以进一步简化:

import Control.Arrow

valid :: [(String, Int)]-> [String]-> [(String, Int)]
valid dict = map (id &&& scores) . filter (flip checks dict)