Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

what is the correct Haskell syntax for this 'where' clause?

what is the appropriate correction for this syntax? Is it an issue white space? I copied the whitespace used in examples in LYAH, also tried other variations gleaned from answers on SO.

I’m sure there’s better ways to write this, but I’m not really any good at point free code yet. I’m novice level and trying to master the very elementary syntax things that continue to trip me up by doing lots of codewars exercises.

import Data.List (findIndices)

basicOp :: Char -> Int -> Int -> Int
basicOp x y z = (operations  !! (op x)) y z
    where op x = head $ findIndices (== x) "+-*/" :: Char -> Int
    operations = [(+), (-), (*), (div)]  :: [(Int -> Int -> Int)]

when I write like this as one function making reference to two other functions it works.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

import Data.List (findIndices)

operations :: [(Int -> Int -> Int)]
operations = [(+), (-), (*), (div)]

op :: Char -> Int
op x = head $ findIndices (== x) "+-*/" 

basicOp :: Char -> Int -> Int -> Int
basicOp x y z = (operations  !! (op x)) y z

the code with the where clause returns these errors:

codewars.hs:103:34: error:
    • Couldn't match expected type ‘Int’ with actual type ‘Char -> Int’
    • Probable cause: ‘op’ is applied to too few arguments
      In the second argument of ‘(!!)’, namely ‘(op x)’
      In the expression: (operations !! (op x)) y z
      In an equation for ‘basicOp’:
          basicOp x y z
            = (operations !! (op x)) y z
            where
                op x = head $ findIndices (== x) "+-*/" :: Char -> Int
                operations = [(+), ....] :: [(Int -> Int -> Int)]
    |
103 | basicOp x y z = (operations  !! (op x)) y z
    |                                  ^^^^

codewars.hs:104:18: error:
    • Couldn't match expected type ‘Char -> Int’ with actual type ‘Int’
    • Possible cause: ‘($)’ is applied to too many arguments
      In the expression: head $ findIndices (== x) "+-*/" :: Char -> Int
      In an equation for ‘op’:
          op x = head $ findIndices (== x) "+-*/" :: Char -> Int
      In an equation for ‘basicOp’:
          basicOp x y z
            = (operations !! (op x)) y z
            where
                op x = head $ findIndices (== x) "+-*/" :: Char -> Int
                operations = [(+), ....] :: [(Int -> Int -> Int)]
    |
104 |     where op x = head $ findIndices (== x) "+-*/" :: Char -> Int
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

>Solution :

The type of the body of the op x expression is an Int, not a Char -> Int. You should also position operations at the same column as op, so:

basicOp :: Char -> Int -> Int -> Int
basicOp x y z = (operations  !! (op x)) y z
    where op x = head $ findIndices (== x) "+-*/" :: Int
          operations = [(+), (-), (*), (div)]  :: [(Int -> Int -> Int)]

But the types are not necessary, you can simplify this to:

basicOp :: Char -> Int -> Int -> Int
basicOp x = (operations  !! op x)
    where op x = head $ findIndices (== x) "+-*/"
          operations = [(+), (-), (*), (div)]

and work with lookup :: Eq a => a -> [(a, b)] -> Maybe b:

basicOp :: Char -> Int -> Int -> Int
basicOp x | Just y <- lookup x operations = y
          | otherwise = …
    where operations = [('+', (+)), ('-', (-)), ('*', (*)), ('/', div)]

where is an expression that is then evaluated if the key is not found

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading