Haskell code explanation - haskell

xs = [1,2,3]::[Float]
ys = map (+) xs
This was a question in an old test and there is no solution sheet.
The questions:
1) What kind of signature does ys have?
2) Explain why and draw how ys looks like
For the first question I know that xs is of type float and so should ys(I run the program in ghci too).
As for the second one I have no idea, because when I run the code nothing happens. When I run it and the run ys on a separate row I get an error.
Can someone help me with a hint?

For the first question I know that xs is of type float
er, no. xs has type [Float]: a list of floats.
and so should ys
ys does not have the same type as xs. You probably think so because you've read that + requires the arguments and result to have the same type:
(+) :: Num a => a -> a -> a
...or if you instantiate it to Float numbers
(+) :: Float -> Float -> Float
This is correct, nevertheless (+) is not an endomorphism (a function mapping a type to itself, as it would have to be if ys was the same type as xs) because it has two number arguments.
With map (+) you're considering (+) as a function of a single argument, not of two arguments. In most programming languages this would actually be an error, but not so in Haskell: in Haskell, all functions actually have only one argument. Functions with “multiple arguments” are really just functions on interesting types, that make it seem as if you're passing multiple arguments. In particular, the signature of (+) is actually shorthand for:
(+) :: Float -> (Float -> Float)
So, considered as a one-argument function, (+) actually maps numbers to number-endomorphisms. Hence,
map (+) :: [Float] -> [Float -> Float]
and
ys :: [Float -> Float]
– a list of number-functions. Specifically, it's this list:
ys = [(+) 1 , (+) 2 , (+) 3 ]
≡ [(1+) , (2+) , (3+) ]
≡ [\n -> 1+n, \n -> 2+n, \n -> 3+n]
I could, for example, use it like this:
GHCi> let [f,g,h] = ys in [f 3, g 2, h 1]
[4,4,4]
GHCi> map ($ 10) ys -- applies all functions separately to the number 10
[11,12,13]
GHCi> foldr ($) 0 ys -- applies all the functions one after another to 0
6
BTW, IMO you're asking the question the wrong way around. In Haskell, you don't want to consider some code and wonder what type it has – that is more an ML or even Lisp approach. I'd always start with the type signature, and work out the implementation “outside to in” (typed holes are very handy for this). This possibility is one of the big advantages of functional programming in comparison to procedural languages.

I don't have ghci at the moment, apologies if something I say is wrong.
xs is type [Float] and ys is of type [Float -> Float](it's a list of functions that each take a Float and return a Float). ys will be [(+) 1, (+) 2, (+) 3] because map applies (+) to each elements in xs. But you cannot print ys because functions do not derive Show

ys type is [Float -> Float], a list of functions that receive a number return the number +1 (first elem), the number + 2 (the second) and the number +3 (the last).
Please, bear in mind that + is a is applied with a single argument for each list element so it does return another function.
If you wanted to add all the items in the List, you should use a reduce function, such as foldl.
let zs = foldl (+) 0 xs
I hope this helps.
Cristóbal

Related

Haskell: Purpose of the flip function?

I am a bit surprised that this was not asked before. Maybe it is a stupid question.
I know that flip is changing the order of two arguments.
Example:
(-) 5 3
= 5 - 3
= 2
flip (-) 5 3
= 3 - 5
= -2
But why would I need such a function? Why not just change the inputs manually?
Why not just write:
(-) 3 5
= 3 - 5
= -2
One is unlikely to ever use the flip function on a function that is immediately applied to two or more arguments, but flip can be useful in two situations:
If the function is passed higher-order to a different function, one cannot simply reverse the arguments at the call site, since the call site is in another function! For example, these two expressions produce very different results:
ghci> foldl (-) 0 [1, 2, 3, 4]
-10
ghci> foldl (flip (-)) 0 [1, 2, 3, 4]
2
In this case, we cannot swap the arguments of (-) because we do not apply (-) directly; foldl applies it for us. So we can use flip (-) instead of writing out the whole lambda \x y -> y - x.
Additionally, it can be useful to use flip to partially apply a function to its second argument. For example, we could use flip to write a function that builds an infinite list using a builder function that is provided the element’s index in the list:
buildList :: (Integer -> a) -> [a]
buildList = flip map [0..]
ghci> take 10 (buildList (\x -> x * x))
[0,1,4,9,16,25,36,49,64,81]
Perhaps more frequently, this is used when we want to partially apply the second argument of a function that will be used higher-order, like in the first example:
ghci> map (flip map [1, 2, 3]) [(+ 1), (* 2)]
[[2,3,4],[2,4,6]]
Sometimes, instead of using flip in a case like this, people will use infix syntax instead, since operator sections have the unique property that they can supply the first or second argument to a function. Therefore, writing (`f` x) is equivalent to writing flip f x. Personally, I think writing flip directly is usually easier to read, but that’s a matter of taste.
One very useful example of flip usage is sorting in descending order. You can see how it works in ghci:
ghci> import Data.List
ghci> :t sortBy
sortBy :: (a -> a -> Ordering) -> [a] -> [a]
ghci> :t compare
compare :: Ord a => a -> a -> Ordering
ghci> sortBy compare [2,1,3]
[1,2,3]
ghci> sortBy (flip compare) [2,1,3]
[3,2,1]
Sometimes you'll want to use a function by supplying the second parameter but take it's first parameter from somewhere else. For example:
map (flip (-) 5) [1..5]
Though this can also be written as:
map (\x -> x - 5) [1..5]
Another use case is when the second argument is long:
flip (-) 5 $
if odd x
then x + 1
else x
But you can always use a let expression to name the first parameter computation and then not use flip.

How do I fix ‘Eq a’ has kind ‘GHC.Prim.Constraint’ error in haskell?

I am writing a small function in Haskell to check if a list is a palindrome by comparing it with it's reverse.
checkPalindrome :: [Eq a] -> Bool
checkPalindrome l = (l == reverse l)
where
reverse :: [a] -> [a]
reverse xs
| null xs = []
| otherwise = (last xs) : reverse newxs
where
before = (length xs) - 1
newxs = take before xs
I understand that I should use [Eq a] in the function definition because I use the equality operator later on, but I get this error when I compile:
Expected kind ‘*’, but ‘Eq a’ has kind ‘GHC.Prim.Constraint’
In the type signature for ‘checkPalindrome’:
checkPalindrome :: [Eq a] -> Bool
P.s Feel free to correct me if I am doing something wrong with my indentation, I'm very new to the language.
Unless Haskell adopted a new syntax, your type signature should be:
checkPalindrome :: Eq a => [a] -> Bool
Declare the constraint on the left hand side of a fat-arrow, then use it on the right hand side.
Unlike OO languages, Haskell makes a quite fundamental distinction between
Constraints – typeclasses like Eq.
Types – concrete types like Bool or lists of some type.
In OO languages, both of these would be represented by classes†, but a Haskell type class is completely different. You never have “values of class C”, only “types of class C”. (These concrete types may then contain values, but the classes don't.)
This distinction may seem pedantic, but it's actually very useful. What you wrote, [Eq a] -> Bool, would supposedly mean: each element of the list must be comparable... but comparable to what? You could have elements of different type in the list, how do you know that these elements are comparable to each other? In Haskell, that's no issue, because whenever the function is used you first settle on one type a. This type must be in the Eq class. The list then must have all elements from the same type a. This way you ensure that each element of the list is comparable to all of the others, not just, like, comparable to itself. Hence the signature
checkPalindrome :: Eq a => [a] -> Bool
This is the usual distinction on the syntax level: constraints must always‡ be written on the left of an => (implication arrow).
The constraints before the => are “implicit arguments”: you don't explicitly “pass Eq a to the function” when you call it, instead you just pass the stuff after the =>, i.e. in your example a list of some concrete type. The compiler will then look at the type and automatically look up its Eq typeclass instance (or raise a compile-time error if the type does not have such an instance). Hence,
GHCi, version 7.10.2: http://www.haskell.org/ghc/ :? for help
Prelude> let palin :: Eq a => [a] -> Bool; palin l = l==reverse l
Prelude> palin [1,2,3,2,1]
True
Prelude> palin [1,2,3,4,5]
False
Prelude> palin [sin, cos, tan]
<interactive>:5:1:
No instance for (Eq (a0 -> a0))
(maybe you haven't applied enough arguments to a function?)
arising from a use of ‘palin’
In the expression: palin [sin, cos, tan]
In an equation for ‘it’: it = palin [sin, cos, tan]
...because functions can't be equality-compared.
†Constraints may in OO also be interfaces / abstract base classes, which aren't “quite proper classes” but are still in many ways treated the same way as OO value-classes. Most modern OO languages now also support Haskell-style parametric polymorphism in addition to “element-wise”/covariant/existential polymorphism, but they require somewhat awkward extends trait-mechanisms because this was only implemented as an afterthought.
‡There are also functions which have “constraints in the arguments”, but that's a more advanced concept called rank-n polymorphism.
This is really an extended comment. Aside from your little type error, your function has another problem: it's extremely inefficient. The main problem is your definition of reverse.
reverse :: [a] -> [a]
reverse xs
| null xs = []
| otherwise = (last xs) : reverse newxs
where
before = (length xs) - 1
newxs = take before xs
last is O(n), where n is the length of the list. length is also O(n), where n is the length of the list. And take is O(k), where k is the length of the result. So your reverse will end up taking O(n^2) time. One fix is to just use the standard reverse function instead of writing your own. Another is to build up the result recursively, accumulating the result as you go:
reverse :: [a] -> [a]
reverse xs0 = go [] xs0
go acc [] = acc
go acc (x : xs) = go (x : acc) xs
This version is O(n).
There's another source of inefficiency in your implementation:
checkPalindrome l = (l == reverse l)
This isn't nearly as bad, but let's look at what it does. Suppose we have the string "abcdefedcba". Then we test whether "abcdefedcba" == "abcdefedcba". By the time we've checked half the list, we already know the answer. So we'd like to stop there! There are several ways to accomplish this. The simplest efficient one is probably to calculate the length of the list as part of the process of reversing it so we know how much we'll need to check:
reverseCount :: [a] -> (Int, [a])
reverseCount xs0 = go 0 [] xs0 where
go len acc [] = (len, acc)
go len acc (x : xs) = len `seq`
go (len + 1) (x : acc) xs
Don't worry about the len `seq` bit too much; that's just a bit of defensive programming to make sure laziness doesn't make things inefficient; it's probably not even necessary if optimizations are enabled. Now you can write a version of == that only looks at the first n elements of the lists:
eqTo :: Eq a => Int -> [a] -> [a] -> Bool
eqTo 0 _ _ = True
eqTo _ [] [] = True
eqTo n (x : xs) (y : ys) =
x == y && eqTo (n - 1) xs ys
eqTo _ _ _ = False
So now
isPalindrome xs = eqTo ((len + 1) `quot` 2) xs rev_xs
where
(len, rev_xs) = reverseCount xs
Here's another way, that's more efficient and arguably more elegant, but a bit tricky. We don't actually need to reverse the whole list; we only need to reverse half of it. This saves memory allocation. We can use a tortoise and hare trick:
splitReverse ::
[a] ->
( [a] -- the first half, reversed
, Maybe a -- the middle element
, [a] ) -- the second half, in order
splitReverse xs0 = go [] xs0 xs0 where
go front rear [] = (front, Nothing, rear)
go front (r : rs) [_] = (front, Just r, rs)
go front (r : rs) (_ : _ : xs) =
go (r : front) rs xs
Now
isPalindrome xs = front == rear
where
(front, _, rear) = splitReverse xs
Now for some numbers, using the test case
somePalindrome :: [Int]
somePalindrome = [1..10000] ++ [10000,9999..1]
Your original implementation takes 7.523s (2.316 mutator; 5.204 GC) and allocates 11 gigabytes to build the test list and check if it's a palindrome. My counting implementation takes less than 0.01s and allocates 2.3 megabytes. My tortoise and hare implementation takes less than 0.01s and allocates 1.7 megabytes.

parenthesis in Haskell functions

I just want to know how do we know which functions need brackets () and which ones do not? For example
replicate 100 (product (map (*3) (zipWith max [1,2,3,4,5] [4,5,6,7,8])))
works fine. But
replicate 100 (product (map (*3) (zipWith (max [1,2,3,4,5] [4,5,6,7,8]))))
does not work. It is because I put a set of brackets for zipWith. In this small example, zipWith and max do not have brackets, but replicate, product and map do. In general is there a way to know/figure out which functions need brackets and which ones dont.
Function application is left associative. So, when you write an expression like:
f g h x
it means:
((f g) h) x
And also the type of zipWith provides a clue:
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
it says that zipWith has 3 parameters: a function and two lists.
When you write:
zipWith (max [1,2,3,4,5] [4,5,6,7,8])
The interpreter will understand that
max [1,2,3,4,5] [4,5,6,7,8]
will be the first parameter to zipWith, which is type incorrect. Note that zipWith expects a function of two arguments as its first argument and, as pointed out by #Cubic, max [1,2,3,4,5] [4,5,6,7,8] will return the maximum
between these two lists according the usual lexicographic order, which will be of type [a], for some type a which is instance of Ord and Num. Said that, the error become evident since you are trying to pass a value of type
(Num a, Ord a) => [a]
where a value of type
(a -> b -> c)
is expected.
Rodrigo gave the right answer. I'll just add that it is a misconception to think that some functions need parentheses, while others don't.
This is just like in school math:
3 * (4+5)
It is simply not the case that + expressions need parentheses and * expressions don't need them in general.
In Haskell, you can always get away without parentheses at all. Whenever you need to enclose an expression in parentheses, the alternative is to introduce a local name and bind it to that expression, then use the name instead of the expression.
In your example:
replicate 100 (product (map (*3) (zipWith max [1,2,3,4,5] [4,5,6,7,8])))
let list1 = product list2
list2 = map thrice list3
thrice x = x*3
list3 = zipWith max [1,2,3,4,5] [4,5,6,7,8]
in replicate 100 list1
In fact, I often write functions top down thus:
foo x y z = result
where
result = ...
...
However, as it was said before, expressions that consist of function applications can also often be written without parentheses by making use of (.) and ($) and in such cases, the top down approach from above may be overly verbose and the following would be much clearer (because there is no noise through newly introduced names):
replicate 100
. product
. map (*3)
$ zipWith max [1..5] [4..8]

What does foldr do in Haskell? [duplicate]

This question already has answers here:
How does foldr work?
(11 answers)
Closed 6 years ago.
So I came across the foldr function in Haskell which from what I pick up, you can use to calculate the product and sum of a list:
foldr f x xs
foldr (*) 1 [1..5] = 120
foldr (+) 0 [1..5] = 15
And adding numbers onto the x part would like, add on to the overall sum or multiply onto the final product
What does foldr actually do and why would anyone use it instead of the built in functions 'sum' or 'product' etc?
sum and product are themselves defined using fold (foldl, not foldr, but let's set aside that distinction for now), so in a sense you are using fold when using those functions. Likewise or, and, concat and many more are all defined using folds as well. So that's already one reason for folds to exist: many of the standard functions can be defined using them instead of having redundant code.
So when would you use folds directly? When doing something that there isn't already a specific function for, i.e. when you want to combine the elements of the list using something other than + or * (or ||, && or ++).
Say you have a list of single-digit numbers and you want to "concatenate" them into one number:
concatDigits = foldl (\acc d -> d + acc * 10) 0
Now concatDigits [1,2,3] gives you 123.
Or you've defined some datastructure and you want to convert lists to it:
fromList = foldr insert empty`
In fact that's how fromList is commonly defined for many data structures.
The Wikipedia entry has a good illustration of what foldr does to a list and how it differs from foldl.
The list [1,2,3] is generated by the cons operator (:) and the empty list [] by this expression tree:
:
/ \
1 :
/ \
2 :
/ \
3 []
foldr f z replaces the cons operator nodes with f and the empty list with z:
By contrast, foldl f z reorients the expression tree and repositions the zero element at the opposite end of the computation:
Some observations:
Note that foldr (:) [] leaves a list unchanged:
foldr (:) [] [1..10] == [1..10]
This makes sense since we are simply replacing the cons operator with itself and the empty list with the empty list and thus not changing anything.
If we replace the empty list with some other list we should be able to append two lists, e.g.:
foldr (:) [9,8,7] [1,2,3] == [1,2,3,9,8,7]
The cons operator may be thought of a way to add an element to a list:
(:) :: a -> [a] -> [a]
If we define f as:
f :: Int -> [Int] -> [Int]
f a as = [0] ++ [a] ++ as
then foldr f [] will prepend a 0 before each element of the input list:
foldr f [] [1,2,3] == [0,1,0,2,0,3]
Data.Set has a function insert whose signature is structually similar to that of (:):
insert :: Ord a => a -> Set a -> Set a
Indeed, we can convert a list to a Set using foldr
import qualified Data.Set as S
foldr S.insert S.empty [1,2,3]
Note how the empty list is replaced with the empty set - S.empty.
This is the idiomatic approach to building up data structures one element at a time - e.g. hash maps, tries, trees, etc.

Composing a chain of 2-argument functions

So I have a list of a functions of two arguments of the type [a -> a -> a]
I want to write a function which will take the list and compose them into a chain of functions which takes length+1 arguments composed on the left. For example if I have [f,g,h] all of types [a -> a -> a] I need to write a function which gives:
chain [f,g,h] = \a b c d -> f ( g ( h a b ) c ) d
Also if it helps, the functions are commutative in their arguments ( i.e. f x y = f y x for all x y ).
I can do this inside of a list comprehension given that I know the the number of functions in question, it would be almost exactly like the definition. It's the stretch from a fixed number of functions to a dynamic number that has me stumped.
This is what I have so far:
f xs = f' xs
where
f' [] = id
f' (x:xs) = \z -> x (f' xs) z
I think the logic is along the right path, it just doesn't type-check.
Thanks in advance!
The comment from n.m. is correct--this can't be done in any conventional way, because the result's type depends on the length of the input list. You need a much fancier type system to make that work. You could compromise in Haskell by using a list that encodes its length in the type, but that's painful and awkward.
Instead, since your arguments are all of the same type, you'd be much better served by creating a function that takes a list of values instead of multiple arguments. So the type you want is something like this: chain :: [a -> a -> a] -> [a] -> a
There are several ways to write such a function. Conceptually you want to start from the front of the argument list and the end of the function list, then apply the first function to the first argument to get something of type a -> a. From there, apply that function to the next argument, then apply the next function to the result, removing one element from each list and giving you a new function of type a -> a.
You'll need to handle the case where the list lengths don't match up correctly, as well. There's no way around that, other than the aforementioned type-encoded-lengths and the hassle associate with such.
I wonder, whether your "have a list of a functions" requirement is a real requirement or a workaround? I was faced with the same problem, but in my case set of functions was small and known at compile time. To be more precise, my task was to zip 4 lists with xor. And all I wanted is a compact notation to compose 3 binary functions. What I used is a small helper:
-- Binary Function Chain
bfc :: (c -> d) -> (a -> b -> c) -> a -> b -> d
bfc f g = \a b -> f (g a b)
For example:
ghci> ((+) `bfc` (*)) 5 3 2 -- (5 * 3) + 2
17
ghci> ((+) `bfc` (*) `bfc` (-)) 5 3 2 1 -- ((5 - 3) * 2) + 1
5
ghci> zipWith3 ((+) `bfc` (+)) [1,2] [3,4] [5,6]
[9,12]
ghci> getZipList $ (xor `bfc` xor `bfc` xor) <$> ZipList [1,2] <*> ZipList [3,4] <*> ZipList [5,6] <*> ZipList [7,8]
[0,8]
That doesn't answers the original question as it is, but hope still can be helpful since it covers pretty much what question subject line is about.

Resources