I learn Haskell.
This is not an operator, because an operator must to have two parameters:
(###) :: Int -> Int -> Int -> Int
(###) a b c = a + b + c
But what about this case:
(###) :: Int -> Int -> (Int -> Int)
(###) a b = \c -> a + b + c
This function has two parameters, but returns a function... Is it an operator now? I think it is not an operator still, because second variant is partial applied first. But I am not sure I am right. Can operator return a function?
There is no rule that says an operator has to have two parameters and in fact, semantically all functions in Haskell only ever take a single parameter. Your two examples are exactly identical as the type Int -> Int -> Int -> Int is implicitly bracketed as Int -> (Int -> (Int -> Int)).
You can use your operator like this
(1 ### 2) 3
or
1 ### 2 $ 3
Related
I have two variables,
let x = 3
let y = 4
And I have a bunch of operators in the form of Plus, Minus, Lt, Gt, Gte, etc.
data Operator = Plus | Minus | Divide | Gt | Lt ....
I am trying to write a function that takes in an Operator type and returns the actual operator. Like:
returnOperator :: Operator -> (Int->Int->a)
returnOperator op = case op of
Plus -> (+)
Minus -> (-)
Gt -> (>)
...etc
So I can do:
let output_op = returnOperator (Plus)
let z = x `output_op` y
z = 7
As an example. However, my returnOperator function as written gives an error:
Couldn't match type ‘a’ with ‘Int’
‘a’ is a rigid type variable bound by
the type signature for:
returnOp :: forall a. Operator -> Int -> Int -> a
Any suggestions on how to fix this issue?
One way is to separate your operators by type.
data BoolOperator = Gt | Lt | ...
data IntOperator = Plus | Minus | Divide | ...
boolOp :: BoolOperator -> Int -> Int -> Bool
intOp :: IntOperator -> Int -> Int -> Int
A more advanced way, of questionable marginal utility, is to use a GADT.
data Operator a where
Plus :: Operator Int
Gt :: Operator Bool
returnOperator :: Operator a -> Int -> Int -> a
returnOperator Plus = (+)
returnOperator Gt = (<)
Note that this doesn't buy you as much as you might think at first; in particular, any homogeneous data structure like lists or Maps will not be able to store both Plus and Gt, because they have different types.
I have a hard time to understand Currying in Haskell. I was not able to understand the already existing answers to this topic. I want to understand what the difference is between:
(Int -> Int) -> Int
and
Int -> (Int - > Int)
I think the answer has something to do with currying. I have already consulted some resources about the topic and I have got an idea.
Functions that have several parameters can be described as an array of elementary operations with one input and one output.
According to the online tutorial learnyouahaskell:
"Doing max 4 5 first creates a function that takes a parameter and returns either 4 or that parameter, depending on which is bigger. Then, 5 is applied to that function and that function produces our desired result."
So in this case the elementary basic operations are just comparing two values. And the first operation is
if "lowest value possible" > 4 then "lowest value possible" otherwise 4
The second operation is
if 4 > 5 then 4 otherwise 5
This would represent Int -> (Int -> Int) but what would (Int -> Int) -> Int be?
Int -> (Int -> Int)
is the same type as
Int -> Int -> Int
and is the type of a curried two-arguments function, both being integers. That is it is a function which takes an integer argument and returns a function, whose argument is another integer, and which finally returns an integer.
Possible calls are f 3 2 and f (7+4) (5*8).
Possible definitions are f a b = a+b and f a b = a*a+42*b.
Instead,
(Int -> Int) - > Int
is not a binary function, curried or not. It is a function with a single argument, and this argument is a function Int -> Int. The final result is an integer.
Possible calls are f (\x -> x+1), f id, and f g where g n = n*4+5.
Possible definitions are f h = h 45 and f h = h (h 6) + h 7 + 9.
The idea of partial function application is a hallmark of Haskell.
Exploiting partial application is natural. It is much how we think.
I fill my glass half with tea. Then I fill it completely with lemonaid.
m2 = max 4 --partial application (Int -> Int)
m2 5 -- full application (Int -> Int) -> Int
All functions in Haskell are curried. It is sometimes necessary to disable it with uncurry
m3 = uncurry max
m4 = m3 4 -- does not become (Int -> Int)
m4 3 -- is not (Int -> Int) -> Int -> Int
Does not work and the error has to do with partial application (Int -> Int) because the function now requires two parameters.
I am a Haskell beginner currently working through The Craft of Functional Programming 2nd Edition. One of the exercises in the book asks me to write an averageThree function, which I have did, and then a howManyAboveAverage function using the averageThree function.
I was a bit stuck on how to do this but I found a similar problem here. I used the solution given in my code however I am getting a parse error [FIXED].
Here is my new code:
averageThree :: Int -> Int -> Int -> Float
averageThree a b c = fromIntegral (a + b + c) / 3
howManyAverageThree :: Int -> Int -> Int -> Int
howManyAverageThree a b c = length $ filter (> avg) the_three
where avg = averageThree a b c
the_three = fromIntegral <$> [a,b,c]
EDIT: New Error
Error trace:
[1 of 1] Compiling Main ( average.hs, interpreted )
average.hs:7:36: Not in scope: `<$>'
Failed, modules loaded: none.
I use ghci version 7.6.3 for compilation. Since I'm following a textbook example I need to preserve the function signatures. How can I modify this code such that I no longer get the above error?
In Haskell, indentation does matter. You need to match the indentation in your where clause:
howManyAverageThree :: Int -> Int -> Int -> Int
howManyAverageThree a b c = length $ filter (> avg) the_three
where avg = averageThree a b c
the_three = fromIntegral[a b c]
EDIT:
Following your edit to the question, you need to look more closely at the definition of the_three:
the_three = fromIntegral[a b c]
fromIntegral has type :: (Integral a, Num b) => a -> b
If you want to the_three to be a list of numbers, you need to do a few things.
First, your list constructions needs ,'s inside it. Second, you need to map fromIntegral over each element of that list.
import Control.Applicative((<$>))
....
the_three = fromIntegral <$> [a,b,c]
The code bellow works pretty well for input like this:
*Main> eval 'y' (21 :: Int)
42
*Main> eval 'x' 'a'
42
*Main> eval (21 :: Int) (21 :: Int)
42
*Main> eval (42 :: Int) 'a'
42
The general problem behind this is that I want to add two things. Adding to Ints is not hard to realize (it's already built in). But I've a given function (here geti) which resolves Chars to Ints and my add-function now should add two Ints as well as Int combined with Char (in every permutation). The Chars are converted by the geti function to Ints so that they can be added. I've thought about an other solution which might be:
eval (geti 'a') (42 :: Int)
but that is not possible for me.
So in general my question is: is there any way to make this simpler or implement it more elegant?
This is the code:
-- A static function only used to resolve some demo data
geti :: Char -> Int
geti c | c == 'x' = 42
| c == 'y' = 21
| c == 'z' = 10
| otherwise = 0
-- Here comes the problem:
class Eval t1 t2 where
eval :: t1 -> t2 -> Int
instance Eval Int Int where
eval a b = a + b
instance Eval Int Char where
eval a c = a + (geti c)
instance Eval Char Int where
eval c b = (geti c) + b
instance Eval Char Char where
eval c1 c2 = (geti c1) + (geti c2)
P.S.: I've also tried to combine the solution from here with an "generic" (yes, it's Java language, but I'm new to Haskell ... sry) function but that didn't work ...
I think it would be more straight forward to build a type class for "can be converted to Int" and use that to implement eval:
class Intable a where
intify :: a -> Int
instance Intable Int where
intify = id
instance Intable Char where
intify = geti
eval :: (Intable a, Intable b) => a -> b -> Int
eval a b = intify a + intify b
I want to know whether shift is a higher order function or not.
chartoInt :: Char -> Int
chartoInt c = ord c
Inttochar :: Int -> Char
Inttochar n = chr n
shift :: Int -> Char -> Char
shift n c = Inttochar (chartoInt c + n)
None of these functions are higher order functions, because none of these functions take a function as a parameter.
shift's parameters are n (an Int) and c (a Char): neither are functions.
(Also: Inttochar should be inttochar: function names in Haskell cannot start with an upper case letter.)
Here's a higher order function that looks like your shift:
higherShift :: (Int -> Char) -> Int -> Char -> Char
higherShift f n c = f (chartoInt c + n)
shift = higherShift inttochar -- same as your original shift
Or, perhaps more usefully:
anotherHigherShift :: (Int -> Int) -> Char -> Char
anotherHigherShift f c = inttochar (f (chartoInt c))
shift n = anotherHigherShift (+n) -- same as your original shift
You can read the type signature for anotherHigherShift as saying that
it's a function
whose first parameter is a function (this function takes an Int and returns an Int)
whose second parameter is a Char
and which returns a Char
(+n) is shorthand for \m -> m + n.
It is.
The shift is a higher order function.
shift :: Int -> (Char -> Char) -- The long prototype.
It get Int and return function getting Char and returning Char.
P.S.
You should write inttochar.
There is informal rule: take a look at function's type. If it contains (with necessity [1]) braces, than it's a higher order function.
[1] In the meaning that omitting them changes the type.
And now take a look at types of your function and functions from first answer from this point of view. It's simple.