質問

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?

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

役に立ちましたか?

解決

In Haskell everything has a type right? So if checks word dict then ... has a specific type, in this case (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?

To avoid this obvious quagmire, Haskell requires an else clause always. Its more accurate to think of if then else as something like C's foo ? bar : baz (ternary operator).

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.

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.

他のヒント

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.

Alternatively, you can do this with the "do" notation:

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帰属
所属していません StackOverflow
scroll top