I'm currently learning Haskell and I must say, I am having a terrible time.
I've been tasked with the exercise of creating a function, evens, which takes a value, x, and returns a list of all even values from 0 to x.
For example:
> evens 10
> [2,4,6,8,10]
I have been attempting to modify some example functions using list comprehension to achieve my goal however I have simply been riddled with errors, worse even I've tried so many things everything is one big confusing blur.
My last attempt went as follows:
evens :: int -> [int]
evens n = [x | x <- [0..n], filter even x]
It produced the error:
ex1.hs:9:29: error:
• Couldn't match expected type ‘Bool’ with actual type ‘[Integer]’
• In the expression: filter even x
In a stmt of a list comprehension: filter even x
In the expression: [x | x <- [0 .. n], filter even x]
I do see its expecting a Boolean but quite frankly I don't understand where or why.
Any help would be largely appreciated. I have never had any experience with functional programming languages and I am having a hard time figuring out my errors in thought. I feel like I've overthought this one simple question to a point beyond belief.
Just remove the word filter from that code.
The Boolean that is expected is even x. When this value is True, x will be included in the output list.
filter is a list-creating function, but the list comprehension is already creating a list, itself.
In fact, filter p could be coded as
filter p xs = [x | x <- xs, p x]
So using filter on the inside is quite redundant.
About that error message. You say
I do see its expecting a Boolean but quite frankly I don't understand where or why.
But the error message shows us where:
ex1.hs:9:29: error:
• Couldn't match expected type ‘Bool’ with actual type ‘[Integer]’
• In the expression: filter even x
This is where. It is the most immediate culprit: the expression filter even x. It is its actual type, [Integer], that does not match the expected type, Bool.
In a stmt of a list comprehension: filter even x
That expression appears in as a "stmt" statement in our list comprehension,
In the expression: [x | x <- [0 .. n], filter even x]
which is the above full expression. So we just need to read those messages inside-out, to find our way to the (immediate) place of the error.
So from the context of the list comprehension, [ r | x <- xs, q], the q is expected to have the type Bool.
But in itself, q = filter even x has type [Integer], the list of integers.
Why? Because (with the simplified, non-polymorphic types as pertinent to this context)
filter :: (Integer -> Bool) -> [Integer] -> [Integer]
even :: (Integer -> Bool)
-----------------------------------------------------------
filter even :: [Integer] -> [Integer]
xs :: [Integer]
-----------------------------------------------------------
filter even xs :: [Integer]
(read :: as "has type"); whereas
even :: (Integer -> Bool)
x :: Integer
---------------------------
even x :: Bool
And if you're wondering why it's Integer even though you wrote int, the short answer to that is, int is a type variable just like a or b or t or ... . It is not a type, like Int. So you get the default which, here, is Integer.
An alternative but also correct formulation would be,
Prelude> filter (\x -> even x) [1..10]
[2,4,6,8,10]
You can also drop the lambda function here and do
Prelude> filter even [1..10]
[2,4,6,8,10]
More succinctly, in the list-comprehension format.
Prelude> [x | x <- [1..10], even x]
[2,4,6,8,10]
Related
Okay hi guys, I am having a weird problem.
hist :: [Int] -> [Int]
hist x = (foldr (+) 0 x)
The code above does not work, because trying to compile I am getting the error, that expected type '[Int]' could not be matched with actual type 'Int'. I don't get that.
Fun Fact: when I delete the signature, the function works fine!
Does anybody know the fault?
Thank you!
The output of the foldr (+) 0 x will be an Int, not an [Int]. If you want a list, you can use scanl, but I guess, you still want foldr:
hist :: [Int] -> Int
hist = foldr (+) 0
I however strongly advise to make use of sum :: (Foldable f, Num a) => f a -> a which also calculates the sum, but on all types that are instances of Num, and for all Foldables (and thus not only a list).
All I'm trying to do is sum a list of lists. Example of what I want to do:
Input: [[1,2,3],[2,5],[6,7]]
Output: [6,7,13]
The amount of lists inside the outer list can vary, and the amount of integers in each inner list can vary. I've tried a multitude of things, and this is the last one I tried but it doesn't work:
sumSubsets [[x]] = map sum [[x]]
Also, I wanted a base case of sumSubsets [] = [[]] but that causes errors as well. Any help would be appreciated.
You could use
sumSubsets x = map sum x
or even
sumSubsets = map sum
Your previous code,
sumSubsets [[x]] = map sum [[x]]
First performs a pattern match using [[x]] which matches a list containing a single element, which is itself a list containing a single element. Therefore it would work correctly on [[3]]
>> sumSubsets [[3]]
[3]
but not on [[1,2,3]] or [[1],[2]].
I think your problem stems primarily from mixing up types and values, which can happen easily to the beginner, in particular on lists. The whole confusion probably comes from the fact that in Haskell, [] is used as a data constructor as well as a type constructor.
For example, [Int] means "a list of Ints" (a type), but [1] means "the list that contains one element, namely the number 1" (a value -- meaning, the whole list is the value). Both things together:
xs :: [Int]
xs = [1]
When you write polymorphic functions, you abstract from something like the Int. For example, if you want to get the first element of a list, you can define a function that does that for any kind of list -- may they be lists of integers or lists of characters or even lists of lists:
firstElement :: [a] -> a
firstElement (x:xs) = x
[a] means "a list with elements of type a" (a type), and the a alone means "something of type a". firstElement is a function from a list with elements of type a to something of type a. a is a type variable. Since you're not saying what a should be, the function works for all kinds of lists:
*Main> firstElement [1,2,3]
1
*Main> firstElement ['a','b']
'a'
*Main> firstElement [[1,2],[3,4]]
[1,2]
When you wrote [[x]] you were perhaps thinking of the type of the first argument of the function, which would be a list of lists of elements of some type x (x is a type variable). You can still use that, but you have to put it into the type signature of your function (the line that contains the double colon):
sumSubsets :: Num a => [[a]] -> [a]
sumSubsets xs = map sum xs
I've used a here instead of x, since it's more commonly done, but you could use x, too. Unfortunately, the whole thing gets a bit complicated with the Num a which describes additional requirements on the type a (that it belongs to the numbers, since for other things, sum is not defined). To simplify matters, you could write:
sumSubsetsInts :: [[Int]] -> [Int]
sumSubsetsInts xs = map sum xs
I'm having trouble using list pattern with multiple parameters. For example, trying to define:
somefunction (x:xs) (y:ys) = x:[y]
results in Occurs check: cannot construct the infinite type: t0 = [t0].
Basically, I want to take two lists as parameters to a function and manipulate each of them using the (x:xs) pattern matching approach. Why is this wrong and how can I do it right? Thank you much!
EDIT: Update with more code as suggested was needed in answers.
somefunction a [] = [a]:[]
somefunction [] b = [b]:[]
somefunction (x:xs) (y:ys) = x:[y]
EDIT 2: Missed an important update. The error I'm getting with the above code is Occurs check: cannot construct the infinite type: t0 = [[t0]]. I think I understand the problem now.
Your function snippet is perfectly sound:
(! 514)-> ghci
GHCi, version 7.6.3: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> let f (x:xs) (y:ys) = x:[y]
Prelude> :type f
f :: [a] -> [a] -> [a]
But the context contradicts that type, and the type inference give you that error. For instance, I can create a context that will give this error:
Prelude> let g xs ys = xs : ys
Prelude> :type g
g :: a -> [a] -> [a]
And then if I combine f and g like below, then I get your error:
Prelude> let z x y = g x (f x y)
<interactive>:7:20:
Occurs check: cannot construct the infinite type: a0 = [a0]
In the first argument of `f', namely `x'
In the second argument of `g', namely `(f x y)'
In the expression: g x (f x y)
Prelude>
To understand you error properly, you will need to examine (or post) enough context.
The problem is with all 3 lines taken together:
somefunction a [] = [a]:[]
somefunction [] b = [b]:[]
somefunction (x:xs) (y:ys) = x:[y]
None of them are incorrect taken on their own. The problem is that the three equations are inconsistent about the return type of somefunction.
From the last equation, we can see that both arguments are lists (since you pattern match on them using the list constructor :).
From the last equation, we can see that the return type is a list whose elements must be the same type as the elements of the argument lists (which must also both be the same type), since the return value is x:[y] (which is more often written [x, y]; just the list containing only the two elements x and y) and x and y were elements of the argument lists. So if x has type t0, the arguments to somefunction both have type [t0] and the return type is [t0].
Now try to apply those facts to the first equation. a must be a list. So [a] (the list containing exactly one element a) must be a list of lists. And then [a]:[] (the list whose first element is [a] and whose tail is empty - also written [[a]]) must be a list of lists of lists! If the parameter a has type [t0] (to match the type we figured out from looking at the last equation), then [a] has type [[t0]] and [a]:[] (or [[a]]) has type [[[t0]]], which is the return type we get from this equation.
To reconcile what we learned from those two equations we need to find some type expression to use for t0 such that [t0] = [[[t0]]], which also requires that t0 = [[t0]]. This is impossible, which is what the error message Occurs check: cannot construct the infinite type: t0 = [[t0]] was about.
If your intention was to return one of the parameters as-is when the other one is empty, then you need something more like:
somefunction a [] = a
somefunction [] b = b
somefunction (x:xs) (y:ys) = [x, y]
Or it's possible that the first two equations were correct (you intend to return a list of lists of lists?), in which case the last one needs to be modified. Without knowing what you wanted the function to do, I can't say.
May be you want to write:
somefunction xs [] = xs
somefunction [] ys = ys
somefunction (x:xs) (y:ys) = x : y : []
You have extra brackets. And your definition of x : y not contains []. So compiler think, y is already a list
Here's what I've got so far...
fun positive l1 = positive(l1,[],[])
| positive (l1, p, n) =
if hd(l1) < 0
then positive(tl(l1), p, n # [hd(l1])
else if hd(l1) >= 0
then positive(tl(l1), p # [hd(l1)], n)
else if null (h1(l1))
then p
Yes, this is for my educational purposes. I'm taking an ML class in college and we had to write a program that would return the biggest integer in a list and I want to go above and beyond that to see if I can remove the positives from it as well.
Also, if possible, can anyone point me to a decent ML book or primer? Our class text doesn't explain things well at all.
You fail to mention that your code doesn't type.
Your first function clause just has the variable l1, which is used in the recursive. However here it is used as the first element of the triple, which is given as the argument. This doesn't really go hand in hand with the Hindley–Milner type system that SML uses. This is perhaps better seen by the following informal thoughts:
Lets start by assuming that l1 has the type 'a, and thus the function must take arguments of that type and return something unknown 'a -> .... However on the right hand side you create an argument (l1, [], []) which must have the type 'a * 'b list * 'c list. But since it is passed as an argument to the function, that must also mean that 'a is equal to 'a * 'b list * 'c list, which clearly is not the case.
Clearly this was not your original intent. It seems that your intent was to have a function that takes an list as argument, and then at the same time have a recursive helper function, which takes two extra accumulation arguments, namely a list of positive and negative numbers in the original list.
To do this, you at least need to give your helper function another name, such that its definition won't rebind the definition of the original function.
Then you have some options, as to which scope this helper function should be in. In general if it doesn't make any sense to be calling this helper function other than from the "main" function, then it should not be places in a scope outside the "main" function. This can be done using a let binding like this:
fun positive xs =
let
fun positive' ys p n = ...
in
positive' xs [] []
end
This way the helper function positives' can't be called outside of the positive function.
With this take care of there are some more issues with your original code.
Since you are only returning the list of positive integers, there is no need to keep track of the
negative ones.
You should be using pattern matching to decompose the list elements. This way you eliminate the
use of taking the head and tail of the list, and also the need to verify whether there actually is
a head and tail in the list.
fun foo [] = ... (* input list is empty *)
| foo (x::xs) = ... (* x is now the head, and xs is the tail *)
You should not use the append operator (#), whenever you can avoid it (which you always can).
The problem is that it has a terrible running time when you have a huge list on the left hand
side and a small list on the right hand side (which is often the case for the right hand side, as
it is mostly used to append a single element). Thus it should in general be considered bad
practice to use it.
However there exists a very simple solution to this, which is to always concatenate the element
in front of the list (constructing the list in reverse order), and then just reversing the list
when returning it as the last thing (making it in expected order):
fun foo [] acc = rev acc
| foo (x::xs) acc = foo xs (x::acc)
Given these small notes, we end up with a function that looks something like this
fun positive xs =
let
fun positive' [] p = rev p
| positive' (y::ys) p =
if y < 0 then
positive' ys p
else
positive' ys (y :: p)
in
positive' xs []
end
Have you learned about List.filter? It might be appropriate here - it takes a function (which is a predicate) of type 'a -> bool and a list of type 'a list, and returns a list consisting of only the elements for which the predicate evaluates to true. For example:
List.filter (fn x => Real.>= (x, 0.0)) [1.0, 4.5, ~3.4, 42.0, ~9.0]
Your existing code won't work because you're comparing to integers using the intversion of <. The code hd(l1) < 0 will work over a list of int, not a list of real. Numeric literals are not automatically coerced by Standard ML. One must explicitly write 0.0, and use Real.< (hd(l1), 0.0) for your test.
If you don't want to use filter from the standard library, you could consider how one might implement filter yourself. Here's one way:
fun filter f [] = []
| filter f (h::t) =
if f h
then h :: filter f t
else filter f t
What doesx :: xs' mean?
I dont have much functional experience but IIRC in F# 1 :: 2 :: 3 :: [];; creates an array of [1,2,3]
so what does the ' do?
let rec sum xs =
match xs with
| [] -> 0
| x :: xs' -> x + sum xs'
I think sepp2k already answered most of the question, but I'd like to add a couple of points that may clarify how F#/OCaml compiler interprets the code and explain some common uses.
Regarding the ' symbol - this is just a part of a name (a valid identifier starts with a letter and then contains one or more letters, numbers or ' symbols). It is usually used if you have a function or value that is very similar to some other, but is in some way new or modified.
In your example, xs is a list that should be summed and the pattern matching decomposes the list and gives you a new list (without the first element) that you need to sum, so it is called xs'
Another frequent use is when declaring a local utility function that implements the functionality and takes an additional parameter (typically, when writing tail-recursive code):
let sum list =
let rec sum' list res =
match list with
| [] -> res
| x::xs -> sum' xs (res + x)
sum' list 0
However, I think there is usually a better name for the function/value, so I try to avoid using ' when writing code (I think it isn't particularly readable and moreover, it doesn't colorize correctly on StackOverflow!)
Regarding the :: symbol - as already mentioned, it is used to create lists from a single element and a list (1::[2;3] creates a list [1;2;3]). It is however worth noting that the symbol can be used in two different ways and it is also interpreted in two different ways by the compiler.
When creating a list, you use it as an operator that constructs a list (just like when you use + to add two numbers). However, when you use it in the match construct, it is used as a pattern, which is a different syntactic category - the pattern is used to decompose the list into an element and the remainder and it succeeds for any non-empty list:
// operator
let x = 0
let xs = [1;2;3]
let list = x::xs
// pattern
match list with
| y::ys -> // ...
The ' is simply part of the variable name. And yes foo :: bar, where foo is an element of type a and bar is a list of type a, means "the list that has foo as its first element, followed by the elements of bar". So the meaning of the match statement is:
If xs is the empty list, the value is 0. If xs is the list containing the item x followed by the items in xs' the value is x + sum xs'. Since x and xs' are fresh variables, this has the effect that for any non empty list, x will be assigned the value of the first element and xs' will be assigned the list containing all other elements.
Like others have said, the ' is a carryover from mathematics where x' would be said as "x prime"
It's idiomatic in ML-family languages to name a variable foo' to indicate that it's somewhat related to another variable foo, especially in recursions like your code sample. Just like in imperative languages you use i, j for loop indices. This naming convention may be a little surprising since ' is typically an illegal symbol for identifiers in C-like languages.
What does x :: xs' mean?
If you have two variables called x and xs' then x :: xs' creates a new list with x prepended onto the front of xs'.
I dont have much functional experience but IIRC in F# 1 :: 2 :: 3 :: [];; creates an array of [1,2,3]
Not quite. It's a list.
so what does the ' do?
It is treated as an alphabetical character, so the following is equivalent:
let rec sum xs =
match xs with
| [] -> 0
| x :: ys -> x + sum ys
Note that :: is technically a type constructor which is why you can use it in both patterns and expressions.