I was wondering how to write my own sortOn function.
I made a sortBy function and an on function as shown bellow but can't figure out how to combine them and what additional code to add. sortOn is like sortBy but the given function (in here named comp) is applied only once for every element of the list
sortBy :: (a -> a -> Ordering) -> [a] -> [a]
sortBy comp [] = []
sortBy comp [x] = [x]
sortBy comp (x:xs) = insert x (sortBy comp xs)
where
insert x [] = [x]
insert x (y:ys)
| (comp x y == LT) || (comp x y == EQ) = x:y:ys
| otherwise = y:(insert x ys)
on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
on b f x y = b (f x) (f y)
Here's a hint.
If you have a list [a] and you just sort it, the sort function will implicitly make use of the Ord instance for a and specifically the function:
compare :: a -> a -> Ordering
to figure out the relative ordering of pairs of a elements.
Now, if you have a list [a] and a transformation function b, and you want to use sortOn to sort the list of the transformed values, you'll need to figure out the relative ordering of pairs of b elements. How will you do this? Well, you'll implicitly use the Ord instance for b and specifically the function:
compare :: b -> b -> Ordering
In other words, when you try to define:
sortOn :: (Ord b) => (a -> b) -> [a] -> [a]
sortOn f lst = ...
you'll have arguments of type:
f :: a -> b
lst :: [a]
and additional objects of type:
sortBy :: (a -> a -> Ordering) -> [a] -> [a]
on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
compare :: b -> b -> Ordering
Now, can you see how to put them together to define sortOn?
SPOILERS
Further hint: What's the type of compare `on` f?
Further further hint: It's a -> a -> Ordering.
Related
Can some one tell me, why i am getting the following error:
error: [-Wincomplete-patterns, -Werror=incomplete-patterns]
Pattern match(es) are non-exhaustive
In a case alternative: Patterns not matched: []
|
54 | case list of
| ^^^^^^^^^^^^...
Thats my test:
testMinBy :: Test
testMinBy = TestCase $ do
assertEqual "test1" (minBy (\x -> -x) [1,2,3,4,5]) 5
assertEqual "test2" (minBy length ["a", "abcd", "xx"]) "a"
minBy :: Ord b => (a -> b) -> [a] -> a
minBy measure list =
case list of
(x:y:xs) -> minBy measure (if measure x > measure y then y:xs else x:xs)
[x] -> x
Your pattern does not matches with the empty list. Indeed, that is what the error is saying. You can match the empty list, for example with:
minBy :: Ord b => (a -> b) -> [a] -> a
minBy measure list =
case list of
(x:y:xs) -> minBy measure (if measure x > measure y then y:xs else x:xs)
[x] -> x
[] -> error "Empty list"
Your function however is not very efficient: it will recalculate measure multiple times if an item is the current minimum, and will also pack and unpack lists. You can work with an accumulator here, like:
minBy :: Ord b => (a -> b) -> [a] -> a
minBy _ [] = error "Empty list"
minBy f (x:xs) = go xs x (f x)
where go [] y _ = y
go (y₁:ys) y₀ fy₀
| fy₁ < fy₀ = go ys y₁ fy₁
| otherwise = go ys y₀ fy₀
where fy₁ = f y₁
This means it only once has to check for an empty list, and then knows for sure that this is a non-empty list if it enumerates. It also will determine the f of each item exactly once, and uses accumulators to avoid packing and unpacking a "cons".
I want to write a function that returns the longest prefix of a list, where applying a function to every item in that prefix produces a strictly ascending list.
For example:
longestAscendingPrefix (`mod` 5) [1..10] == [1,2,3,4]
longestAscendingPrefix odd [1,4,2,6,8,9,3,2,1] == [1]
longestAscendingPrefix :: Ord b => (a -> b) -> [a] -> [a]
longestAscendingPrefix _ [] = []
longestAscendingPrefix f (x:xs) = takeWhile (\y z -> f y <= f z) (x:xs)
This code snippet produces the error message in the title. It seems the problem lies within that lambda function.
takeWhile has type takeWhile :: (a -> Bool) -> [a] -> [a]. The first parameter is thus a function that maps an element of the list to a Bool. Your lambda expression has type Ord b => a -> a -> Bool, which does not make much sense.
You can work with explicit recursion with:
longestAscendingPrefix :: Ord b => (a -> b) -> [a] -> [a]
longestAscendingPrefix f = go
where go [] = []
go [x] = …
go (x1:x2:xs) = …
where you need to fill in the … parts the last one makes a recursive call to go.
I have the following two type signatures in Haskell:
foo :: (a -> (a,b)) -> a -> [b]
bar :: (a -> b) -> (a -> b -> c) -> a -> c
I want to write a concrete implementation of these two functions but I'm really struggling to understand where to start.
I understand that foo takes a function (a -> (a,b)) and returns a and a list containing b.
And bar takes a function (b -> c) which returns a function (a -> b -> c) which finally returns a and c.
Can anyone show me an example of a concrete implementation?
How do I know where to start with something like this and what goes on the left side of the definition?
You have some misunderstandings there:
I understand that foo takes a function (a -> (a,b)) and returns a and a list containing b.
No, it doesn't return a. It expects it as another argument, in addition to that function.
And bar takes a function (b -> c) which returns a function (a -> b -> c) which finally returns a and c.
Same here. Given g :: a -> b, bar returns a function bar g :: (a -> b -> c) -> a -> c. This function, in turn, given a function h :: (a -> b -> c), returns a function of type a -> c. And so it goes.
It's just like playing with pieces of a puzzle:
foo :: (a -> (a,b)) -> a -> [b]
-- g :: a -> (a,b)
-- x :: a
-- g x :: (a,b)
foo g x = [b] where
(a,b) = g x
bar :: (a -> b) -> (a -> b -> c) -> a -> c
-- g :: a -> b
-- x :: a
-- g x :: b
-- h :: a -> b -> c
-- h x :: b -> c
-- h x (g x) :: c
bar g h x = c where
c = ....
There's not much free choice for us here. Although, there are more ways to get more values of type b, for foo. Instead of ignoring that a in (a,b) = g x, we can use it in more applications of g, so there actually are many more possibilities there, like
foo2 :: (a -> (a,b)) -> a -> [b]
foo2 g x = [b1,b2] where
(a1,b1) = g x
(a2,b2) = g a1
and many more. Still, the types guide the possible implementations. foo can even make use of foo in its implementation, according to the types:
foo3 :: (a -> (a,b)) -> a -> [b]
foo3 g x = b : bs where
(a,b) = g x
bs = ...
So now, with this implementation, the previous two become its special cases: foo g x === take 1 (foo3 g x) and foo2 g x === take 2 (foo3 g x). Having the most general definition is probably best.
In addition to #will-nes's answer, it will be useful to treat (->) as a right-associative infix operator. So something like f: a -> b -> c is the same as f: a -> (b -> c). So this is saying f is a function that takes a value of type a and returns you a value of type b -> c, which is, another function, one that takes a value of type b and returns you a value of type c.
So the types in your example can be re-written as follows
foo :: (a -> (a,b)) -> (a -> [b])
bar :: (a -> b) -> ((a -> (b -> c)) -> (a -> c))
Similarly, you can think of arguments to a function in pieces as well, as being left-associative (like + and -), though there's no explicit operator in this case. foo a b c d e is the same as ((((foo a) b) c) d) e. For example, let's say we have a function f: Int -> Int -> Int (which is the same as f: Int -> (Int -> Int)). You don't have to provide both arguments at once. So you can write g = f 1, which has the type (Int -> Int). And then you can provide an argument to g, like g 2, which has the type Int. f 1 2 and let g = f 1 in g 2 are more or less the same. Here's a more concrete example of how this works:
Prelude> f = (+)
Prelude> g = f 1
Prelude> g 2
3
Prelude> :t f
f :: Num a => a -> a -> a
Prelude> :t g
g :: Num a => a -> a
Prelude> :t g 2
g 2 :: Num a => a
In #will-nes's sample implementation examples, he defines the functions with all of the arguments up front, but you don't have to think of them that way. Just think of f: a -> b -> c as taking a value of type a and returning another function. While most of the methods you encounter will use all of their arguments up-front, there might be cases in which you don't want to do that. Here's an example:
veryExpensive :: A -> B
unstagedFun :: A -> (B -> C) -> C
unstagedFun a f = f (veryExpensive a)
stagedFun :: A -> (B -> C) -> C
stagedFun a = let b = veryExpensive a in \f -> f b
(You can also rewrite the latter as let b = veryExpensive a in ($ b))
Of course, with compiler optimizations, I wouldn't be surprised if the unstaged version staged automatically, but hopefully this offers some motivation for thinking of functions as not having multiple arguments, but rather, as a single argument, but they may return other functions that may themselves return functions (but also only take a single argument).
I'm a relatively experienced Haskell programmer with a few hours of experience, so the answer might be obvious.
After watching A taste of Haskell, I got lost when Simon explained how the append (++) function really works with its arguments.
So, here's the part where he talks about this.
First, he says that (++) :: [a] -> [a] -> [a] can be understood as a function which gets two lists as arguments, and returns a list after the last arrow). However, he adds that actually, something like this happens: (++) :: [a] -> ([a] -> [a]), the function takes only one argument and returns a function.
I'm not sure to understand how the returned function closure gets the first list as it expects one argument as well.
On the next slide of the presentation, we have the following implementation:
(++) :: [a] -> [a] -> [a]
[] ++ ys = ys
(x:xs) ++ ys = x : (xs ++ ys)
If I think that (++) receives two arguments and return a list, this piece of code along with the recursion is clear enough.
If we consider that (++) receives only one argument and returns a list, where does ys come from? Where is the returned function ?
The trick to understanding this is that all haskell functions only take 1 argument at most, it's just that the implicit parentheses in the type signature and syntax sugar make it appear as if there are more arguments. To use ++ as an example, the following transformations are all equivalent
xs ++ ys = ...
(++) xs ys = ...
(++) xs = \ys -> ...
(++) = \xs -> (\ys -> ...)
(++) = \xs ys -> ...
Another quick example:
doubleList :: [Int] -> [Int]
doubleList = map (*2)
Here we have a function of one argument doubleList without any explicit arguments. It would have been equivalent to write
doubleList x = map (*2) x
Or any of the following
doubleList = \x -> map (*2) x
doubleList = \x -> map (\y -> y * 2) x
doubleList x = map (\y -> y * 2) x
doubleList = map (\y -> y * 2)
The first definition of doubleList is written in what is commonly called point-free notation, so called because in the mathematical theory backing it the arguments are referred to as "points", so point-free is "without arguments".
A more complex example:
func = \x y z -> x * y + z
func = \x -> \y z -> x * y + z
func x = \y z -> x * y + z
func x = \y -> \z -> x * y + z
func x y = \z -> x * y + z
func x y z = x * y + z
Now if we wanted to completely remove all references to the arguments we can make use of the . operator which performs function composition:
func x y z = (+) (x * y) z -- Make the + prefix
func x y = (+) (x * y) -- Now z becomes implicit
func x y = (+) ((*) x y) -- Make the * prefix
func x y = ((+) . ((*) x)) y -- Rewrite using composition
func x = (+) . ((*) x) -- Now y becomes implicit
func x = (.) (+) ((*) x) -- Make the . prefix
func x = ((.) (+)) ((*) x) -- Make implicit parens explicit
func x = (((.) (+)) . (*)) x -- Rewrite using composition
func = ((.) (+)) . (*) -- Now x becomes implicit
func = (.) ((.) (+)) (*) -- Make the . prefix
So as you can see there are lots of different ways to write a particular function with a varying number of explicit "arguments", some of which are very readable (i.e. func x y z = x * y + z) and some which are just a jumble of symbols with little meaning (i.e. func = (.) ((.) (+)) (*))
Maybe this will help. First let's write it without operator notation which might be confusing.
append :: [a] -> [a] -> [a]
append [] ys = ys
append (x:xs) ys = x : append xs ys
We can apply one argument at a time:
appendEmpty :: [a] -> [a]
appendEmpty = append []
we could equivalently could have written that
appendEmpty ys = ys
from the first equation.
If we apply a non-empty first argument:
-- Since 1 is an Int, the type gets specialized.
appendOne :: [Int] -> [Int]
appendOne = append (1:[])
we could have equivalently have written that
appendOne ys = 1 : append [] ys
from the second equation.
You are confused about how Function Currying works.
Consider the following function definitions of (++).
Takes two arguments, produces one list:
(++) :: [a] -> [a] -> [a]
[] ++ ys = ys
(x:xs) ++ ys = x : (xs ++ ys)
Takes one argument, produces a function taking one list and producing a list:
(++) :: [a] -> ([a] -> [a])
(++) [] = id
(++) (x:xs) = (x :) . (xs ++)
If you look closely, these functions will always produce the same output. By removing the second parameter, we have changed the return type from [a] to [a] -> [a].
If we supply two parameters to (++) we get a result of type [a]
If we supply only one parameter we get a result of type [a] -> [a]
This is called function currying. We don't need to provide all the arguments to a function with multiple arguments. If we supply fewer then the total number of arguments, instead of getting a "concrete" result ([a]) we get a function as a result which can take the remaining parameters ([a] -> [a]).
Im having trouble inferring the type of this function:
(foldr (.))
I know the types of:
(.) :: (b -> c) -> (a -> b) -> a -> c
foldr :: (a -> b -> b) -> b -> [a] -> b
But now i have no idea what to do.. Is there a method to always be able to infer the type in a systematic way? How would it apply to this case?
I usually follow these steps:
Write their types:
(.) :: (b -> c) -> (a -> b) -> a -> c
foldr :: (a -> b -> b) -> b -> [a] -> b
Make all the type variable name distinct:
(.) :: (b -> c) -> (a -> b) -> a -> c
foldr :: (x -> y -> y) -> y -> [x] -> y
Now since you are applying (.) to the first argument of foldr, you can infer the following relation between the types:
foldr :: ( x -> y -> y ) -> y -> [x] -> y
(.) :: (b -> c) -> (a -> b) -> (a -> c)
From the above you can infer the following relationship:
x ~ (b -> c)
y ~ (a -> b)
y ~ (a -> c)
From the above y, you can infer that both b and c should be same.
The type of foldr (.) should be:
foldr (.) :: y -> [x] -> y
Now replace y and x with the new derived ones, you will get the required type:
foldr (.) :: (a -> b) -> [b -> b] -> a -> b