开发者

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 and where 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 using let or where 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 type Maybe a. This type represents values of type a with possible failure (the Nothing).

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜