简体   繁体   English

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

[英]If else with list comprehension in haskell

I was writing a code which has a if else with list comprehension is it allowed and if not how else can i write this code? 我正在编写一个代码,其中包含if else with list comprehension是否允许,如果没有,我怎么能写这段代码?

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

where check gives a bool value 其中check给出bool值

In Haskell everything has a type right? 在Haskell中,一切都有类型吗? So if checks word dict then ... has a specific type, in this case (String, Int) . 因此, if checks word dict then ...具有特定类型,在这种情况下(String, Int) Imagine if checks word dict was false, we still need to produce something of type (String, Int) so what on earth could we do? 想象一下,如果checks word dict是假的,我们仍然需要生成类型(String, Int)东西,那么我们到底能做什么呢?

To avoid this obvious quagmire, Haskell requires an else clause always. 为了避免这个明显的泥潭,Haskell总是需要一个else子句。 Its more accurate to think of if then else as something like C's foo ? bar : baz if then else像C的foo ? bar : baz那样, if then else更准确地想到if then else东西foo ? bar : baz foo ? bar : baz (ternary operator). foo ? bar : baz (三元运营商)。

In a list comprehension however, there's a nice solution. 然而,在列表理解中,有一个很好的解决方案。 You can put predicates in the body of the comprehension to "guard" what reaches the left side 你可以将谓词放在理解体中,以“保护”到达左侧的内容

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

This basically words by selecting each word in words and then checking checks word dict , if this returns false, we "skip" this element. 这基本上通过选择每个单词词words ,然后检查checks word dict ,如果返回false,我们“跳过”这个元素。

There's actually a connection to monads and something called MonadPlus , but I won't mention this because I think it will only serve to confuse you :) It's alright to treat it as magic for a little bit. 实际上有monad和MonadPlus ,但是我不会提到这个,因为我认为这只会让你感到困惑:)将它视为一点魔力是可以的。

I don't understand why you have been downvoted. 我不明白为什么你被投票了。 As the comment to your question states, you probably want something like this: 正如你的问题的评论所述,你可能想要这样的东西:

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

This is pretty similar to how you would achieve it in Python. 这非常类似于在Python中实现它的方式。

Alternatively, you can do this with the "do" notation: 或者,您可以使用“do”表示法执行此操作:

import Control.Monad (guard)

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

Or, if you don't want to use list comprehensions at all, something like this would work: 或者,如果您根本不想使用列表推导,那么这样的事情会起作用:

import Control.Arrow

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

which can be simplified even further like this: 这可以进一步简化如下:

import Control.Arrow

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM