我正在编写一个代码,其中包含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值
答案 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)