How to define a variable based on an if/then/else statement
I'm trying to translate some python code to haskell. However I reached a point where I'm not sure how to proceed.
if len(prod) % 2 == 0:
ss = float(1.5 * count_vowels(cust))
else:
ss = float(count_consonants(cust)) # muliplicaton by 1 is implied.
if len(cust_factors.intersection(prod_fac开发者_StackOverflow社区tors)) > 0:
ss *= 1.5
return ss
I've tried to translate it to this:
if odd length prod
then ss = countConsonants cust
else ss = countVowels cust
if length (cust intersect
prod) > 0
then ss = 1.5 * ss
else Nothing
return ss
But I keep getting errors of:
parse error on input `='
Any help or words of wisdom on this would be greatly appreciated.
Don't think of programming in Haskell as "if this, then do that, then do the other thing" — the entire idea of doing things in a sequence is imperative. You're not checking a condition and then defining a variable — you're just calculating a result that depends on a condition. In functional programming, if
is an expression and variables are assigned the result of an expression, not assigned inside it.
The most direct translation would be:
let ss = if odd $ length prod
then countConsonants cust
else countVowels cust
in if length (cust `intersect` prod) > 0
then Just $ 1.5 * ss
else Nothing
In Haskell, if
is an expression, not a statement. This means it returns a value (like a function) instead of performing an action. Here's one way to translate your code:
ss = if odd length prod
then countConsinants cust
else countVowels cust
return if length ( cust intersect prod) > 0
then Just $ 1.5 * ss
else Nothing
Here's another way:
return if length ( cust intersect prod) > 0
then Just $ 1.5 * if odd length prod
then countConsinants cust
else countVowels cust
else Nothing
As Matt has pointed out, however, your Python code doesn't return None
. Every code path sets ss
to a number. If this is how it's supposed to work, here's a Haskell translation:
let ss = if odd $ length prod
then countConsonants cust
else countVowels cust
in if length (cust `intersect` prod) > 0
then 1.5 * ss
else ss
If I were you I'd use guards. Maybe I'm a Haskell heathen.
ss prod prodfactors cust | even $ length prod = extratest . (1.5 *) . countvowels cust
| otherwise = extratest . countconsonants cust
where extratest curval | custfactorsintersection prodfactors > 0 = curval * 1.5
| otherwise = curval
I would write it like this in Haskell:
if (not $ null $ cust_factors `intersect` prod_factors)
then ss * 1.5
else ss
where
ss = if (even $ length prod)
then 1.5 * count_vowels cust
else count_cosinants cust
Some comments about what you wrote:
- You can do assignment in Haskell using the
let
andwhere
syntax. In general everything you write in Haskell are expressions. In your case you have to write the whole thing as a single expression and usinglet
orwhere
simplifies that task. return
in Haskell means something different than in Python, it's used for computations with side effects (like IO). For your example there is no need for it.Nothing
is a special value of the typeMaybe a
. This type represents values of typea
with possible failure (theNothing
).
And to answer your direct question.
This Python code
if b:
s = 1
else:
s = 2
would be translated to Haskell to s = if b then 1 else 2
inside a let
or where
clause.
Functional programming is different from imperative programming. Trying to "translate" line by line isn't how Haskell is meant to be used.
To specifically answer your question. "ss" already has a value. It simply isn't possible to give it a different value. ss = ss * 1.5
makes no sense.
精彩评论