Simple error in code in Haskell

Asked

Viewed 273 times

3

I’m starting at Winhugs, programming at Haskell. I’m new at Functional Programming. Since yesterday I am looking to solve the error you have in the code below but unsuccessfully so far. Follow the code:

eq2grau::(Int->Int->Int)->Int 
eq2grau (a1, b1, c1) =
    if(delt1 (a1, b1, c1) > 0 ){
        then (((-b1) + sqrt(delt1(a1 b1 c1))) / (2 * a1))
        then (((-b1) - sqrt(delt1(a1 b1 c1))) / (2 * a1))
        }else
            if((delt1 (a1 b1 c1) == 0 ))
                then ((-b1)/(2 * a1))
                    else a1


delt1::Int->Int->Int->Int
delt1 ah be ce = 
            if(be > 0)
                then ((be * be) - (4 * ah *ce))
                    else ((be * be) - (4 * ah *ce))

Esse é o erro!

  • I don’t program in Haskell, but it seems to me there are two errors in your code, from what I saw in a example: 1. You should not put the conditions of the if in parentheses. 2. You should align the else at the then, that is, put them with the same indentation.

1 answer

4

There are a lot of errors in your code but the good news is that most of them are just syntax error, which is easy to solve :)

Type declaration syntax

The guy statement says eq2grau receives a single argument (which is a crazy function) and returns a Int. The right version takes the three separate arguments.

eq2grau :: (Int->Int->Int)->Int       -- errado
eq2grau :: Int -> Int -> Int -> Int -- certo

You also don’t need a comma in the statement of arguments. The version you wrote gets a single argument (which is a tuple) instead of 3 separate arguments.

-- errado
eq2grau (a1, b1, c1) = ...

-- certo
eq2grau a1 b1 c1 =  ...

Function call syntax

In Haskell the function call syntax is only at the base of space itself, and does not need a comma. The parentheses will wrap the entire call or individual parameters instead of going around the list of parameters.

-- Nesses casos passamos 2 argumentos para f:
f x y
(f x y)
f x (y+z)

-- Já nesses outros casos, f só recebe 1 argumento
f(x,y)  -- f recebe uma tupla como argumento
f(x y)  -- x é uma função e f recebe o valor x aplicado em y.

In your case...

delt1 (a1, b1, c1) > 0  -- errado
delt1 (a1  b1  c1) > 0  -- errado 

(delt a1 b1 c2)    > 0  -- certo
delt a1 b1 c1      > 0  -- também certo

Keys in the if

Haskell doesn’t use keys {} as in C

if( ... ){                -- errado
if ... then ... else ...  -- certo

In Haskell the normal is to group things via identation, even in Python (take care not to mix tabs with spaces, btw)

if x > y then
    "Hello world"
else
    "Goodbye world"

Note that you don’t need parentheses around your parole. You also don’t need to put a return in each branch. The if of Haskell is already an expression with a value, similar to the ternary operator of C, the ?:.

Return of multiple values

Kind of weird this one if with 2 then right?

-- errado
then (((-b1) + sqrt(delt1(a1 b1 c1))) / (2 * a1))
then (((-b1) - sqrt(delt1(a1 b1 c1))) / (2 * a1))

I don’t know how you expected it to work :) The normal in Haskell (or any other language, to tell you the truth) would be to return a list of answers.

-- Precisa mudar o tipo da sua função pra dizer que retorna uma lista...
eq2grau::(Int->Int->Int)-> [Int]

-- .. e mudar os ifs.
if delt1 (a1, b1, c1) > 0 then
    -- Determinante positivo, duas soluções:
    [ ((-b1) + sqrt(delt1 a1 b1 c1)) / (2 * a1),
      ((-b1) - sqrt(delt1 a1 b1 c1)) / (2 * a1) ]
else if delt1 (a1, b1, c1) == 0
    -- Determinante zero, uma solução só:
    [ ((-b1)/(2 * a1)) ]
else
    -- Determinante negativo, nenhuma solução:
    [ ]

if redundant

The identation of this if weird.

delt1 :: Int->Int->Int->Int
delt1 ah be ce = 
    if  be > 0
      then ((be * be) - (4 * ah *ce))
            else ((be * be) - (4 * ah *ce))

The normal would be

delt1 ah be ce = 
    if be > 0 then
        ((be * be) - (4 * ah *ce))
    else
        ((be * be) - (4 * ah *ce))

Also, the two branches of the if are equal. Neither needed the if!

delt1 ah be ce = 
   (be * be) - (4 * ah *ce)

2nd degree integer equation?

It will give a type error when you try to take out the square root of an integer. Why not use floating point numbers for everything?

eq2grau :: Double -> Double > Double -> [Double]
delt1 :: Double -> Double -> Double -> Double

Determinant account appears more than once

This is more of a style suggestion but why not use a let to avoid calculating the determinant more than once? Programming on the basis of Ctrl-c-Ctrl-v is undesirable in any programming language :)

let d = delt1 a1 b1 c1 in

Summing up

The version with all the fixes looks like this. I tested and it worked

eq2grau :: Double -> Double -> Double -> [Double]
eq2grau a1 b1 c1 =
  let d = delt1 a1 b1 c1
  if d > 0 then
    [ ((-b1) + sqrt d) / (2 * a1),
      ((-b1) - sqrt d) / (2 * a1)]
  else if d == 0 then
    [ (-b1)/(2 * a1) ]
  else
    []

delt1 :: Double -> Double -> Double -> Double
delt1 ah be ce =
  (be * be) - (4 * ah *ce)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.