Occurs check: cannot construct the infinte type - haskell

I'm trying to construct a list of all prime numbers using the sieve method:
primes remNum =
let i = head remNum
in i : primes (filter (\(x) -> x mod i /= 0) (tail remNum))
The error that I'm getting is:
* Occurs check: cannot construct the infinite type:
t ~ (a -> a -> a) -> t -> a1
Expected type: [t]
Actual type: [(a -> a -> a) -> t -> a1]
* In the first argument of `head', namely `remNum'
In the expression: head remNum
In an equation for `i': i = head remNum
* Relevant bindings include
i :: t (bound at lib.hs:30:7)
remNum :: [(a -> a -> a) -> t -> a1] (bound at lib.hs:29:8)
primes :: [(a -> a -> a) -> t -> a1] -> [t] (bound at lib.hs:29:1)
I don't understand why remNum is bound to [(a-> a -> a) -> t -> a1] while i is bound to t, since surely head :: [a] -> a would imply remNum::[t]?
So the idea with this is that it is supplied a lazy list of all numbers and then essentially maintains a list of removed values.
It would be called:
numsFrom n = n : numsFrom (n + 1)
primes numsFrom 2

x mod i
is not what you intended. You want to use
x `mod` i
The problem with the first is that since both i and x are from the list, they must have the same type. Let's call that type X. What is X? Well, since we use x mod, it should start with mod's type:
type X = (Integer -> Integer -> Integer) -> …
Since the other "parameter" is i, which has the same type as x, we end up with:
type X = (Integer -> Integer -> Integer) -> X -> …
which is an infinite type.
So the proper solution would be
primes remNum =
let i = head remNum
in i : primes (filter (\(x) -> x `mod` i /= 0) (tail remNum))
or
primes remNum =
let i = head remNum
in i : primes (filter (\(x) -> mod x i /= 0) (tail remNum))
or (with pattern matching)
primes (i:remNums) = x : primes (filter (\x -> mod x i /= 0) remNums)

Related

Haskell: Finding the type of an expression involving map

I am trying to find the type of the following Haskell expression:
map (\x -> x + 1)
Since the map function is partially applied, it will return another function.
In GHCI, the type of the function that is returned is:
let res = map (\x -> x + 1)
:t res
map (\x -> x + 1) :: Num b => [b] -> [b]
Would the type of the above expression be the type of the function that is returned? Any insights are appreciated.
Yes, that is the type of the function which is returned.
But how does GHC figure this out? Well, let's look at the type of just plain map:
map :: (a -> b) -> [a] -> [b]
And now let's look at the type of \x -> x + 1:
(\x -> x + 1) :: Num n => n -> n
(In case you don't know yet, this means that it converts n to n, where n can be any type which is an instance of Num i.e. n is any number type.)
So matching up the types, we get:
map :: (a -> b) -> [a] -> [b]
(\x -> x + 1) :: Num n => n -> n
So:
map (\x -> x + 1) :: Num n => [n] -> [n]
Which is the same as what GHCi reports.

How would you declare the types of these functions in Haskell?

So I'm learning about Haskell at the moment, and I came across this question:
The type of a function f is supposed to be a->[a]->a. The
following definitions of f are incorrect because their types are all
different from a->[a]->a:
i. f x xs = xs
ii. f x xs = x+1
iii. f x xs = x ++ xs
iv. f x (y:ys) = y
My answers as I see it are:
i) f :: a -> a -> a
This is because x or xs can be of any value and is not a list as it does not contain the ':' operator.
ii) f :: Int -> a -> Int
This is because the + operator is used on x, meaning x is of type Int.
iii) f :: Eq a => a -> a -> a
The ++ operators are used, therefore in order to concatenate they must be of the same type..?
iv) f :: a -> [a] -> a
f returns an element from the list.
The last one is definitely wrong, because it can't be of type a -> [a] -> a. Are there any others I did wrong, and why? I'm hoping I can fully understand types and how to find out the types of functions.
i) f :: a -> a -> a
f x xs = xs
This is because x or xs can be of any value and is not a list as it does not contain the ':' operator.
True, but it also does not have to be of the same type!
So, it's actually f :: a -> b -> b.
ii) f :: Int -> a -> Int
f x xs = x+1
This is because the + operator is used on x, meaning x is of type Int.
Correct. (Actually, in Haskell we get Num b => b -> a -> b which generalized the Int to any numeric type, but it's not that important.)
iii) f :: Eq a => a -> a -> a
f x xs = x ++ xs
The ++ operators are used, therefore in order to concatenate they must be of the same type..?
True, but they must be lists. Also, Eq is only needed if you use == or something which compares values.
Here, f :: [a] -> [a] -> [a].
iv) f :: a -> [a] -> a
f x (y:ys) = y
f returns an element from the list.
The type of x does not have to be the same. We get f :: b -> [a] -> a.
i. f x xs = xs
(...)
i) f :: a -> a -> a
Although this can be a type signature, you make it too restrictive. The function takes two parameters x and xs. Initially we can reason that x and xs can have different types, so we say that x :: a, and xs :: b. Since the function returns xs, the return type is b as well, so the type is:
f :: a -> b -> b
f x xs = xs
ii. f x xs = x+1
(...)
ii) f :: Int -> a -> Int
Again you make the function too restrictive. Let us again assume that x :: a and xs :: b have different types. We see that we return x + 1 (or in more canonical form (+) x 1. Since (+) has signature (+) :: Num c => c -> c -> c (we here use c since a is already used), and 1 has signature 1 :: Num d => d, we thus see that we call (+) with x and 1, as a result we know that a ~ c (a and c are the same type), and c ~ d, so as a result we obtain the signature:
f :: Num c => c -> b -> c
f x xs = x+1
iii. f x xs = x ++ xs
(...)
iii) f :: Eq a => a -> a -> a
This is wrong: we here see that f has two parameters, x :: a and xs :: b. We see that we return (++) x xs. Since (++) has signature (++) :: [c] -> [c] -> [c], we thus know that a ~ [c] and b ~ [c], so the type is:
f :: [c] -> [c] -> [c]
f x xs = x ++ xs
iv. f x (y:ys) = y
(...)
iv) f :: a -> [a] -> a
This is again too restrictive. Here we see again two parameters: x and (y:ys). We first generate a type a for x :: a, and (y:ys) :: b, since the pattern of the second parameter is (y:ys), this is a list constructor with as parameters (:) :: c -> [c] -> [c]. As a result we can derive that y :: c, and ys :: [c], furthermore the pattern (y:ys) has type [c]. Since the function returns y, we know that the return type is c, so:
f :: a -> [c] -> c
f x (y:ys) = y
Note: you can let Haskell derive the type of the function itself. In GHCi you can use the :t command to query the type of an expression. For example:
Prelude> f x (y:ys) = y
Prelude> :t f
f :: t1 -> [t] -> t

Finding max list within a list

I was trying to get the list with the greatest sum within a list and then return that list. But when I call the function with
max_list [[1,2],[3,6],[10,34,5]]
it gives me the error:
Exception: a4.hs:65:1-64: Non-exhaustive patterns in function max_list
This is the code:
max_num :: [Int] -> Int
max_num [x] = x
max_num (x:xs) | (max_num xs) > x = maxVal xs
| otherwise = x
max_list :: [[Int]] -> [Int]
max_list [[a]] = head(filter (\x -> (sum_int x) == (max_num [[a]]) [[a]])
My logic is as follows:
I will
Sum the elements in the sublist
Compare that element to see if it equals the max-value of the list
Filter out the values that do not equal the max-value
Example call:
head (filter (\x -> (sum x) == 11) [[1,3],[4,7],[2,5]])
> [4,7]
So in that case I calculated the value 11 before hand and its sum of each element is [4, 11, 7] and it will give me the value whose sum is equal to the max value
There is a function in Data.List called maximumBy with the signature
maximumBy :: (a -> a -> Ordering) -> [a] -> a
and Data.Function has on with the signature
on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
Applied with the compare function (compare :: Ord a => a -> a -> Ordering), we can see how this is exactly what you're looking for.
import Data.List (maximumBy)
import Data.Function (on)
{- for clarity:
compare :: Ord a => b -> b -> Ordering
(compare `on`) :: Ord b => (a -> b) -> a -> a -> Ordering
compare `on` sum :: (Num a, Ord a) => [a] -> [a] -> Ordering
-- well actually [a] is t a for a foldable t, but same diff -}
result = maximumBy (compare `on` sum) [[1,2],[3,6],[10,34,5]]
to implement this yourself, you could write a fold that compares each value according to its sum, recursing until the sum of x is greater than anything that comes before after it.
myMaximumBySum [] = [] -- degenerate case
myMaximumBySum [x] = x -- tautological case
myMaximumBySum (x:xs)
| sum x > sum (myMaximumBySum xs) = x
| otherwise = myMaximumBySum xs
-- or more naturally:
myMaximumBySum = foldr f []
where f x acc = if sum x > sum acc then x else acc

declare function type in function definition in haskell

I just began to learn haskell recently. I have some confusion of declare function type in the function definition. For example if we want to define a foldr function:
foldr :: (a->b->b)->b->[a]->b
foldr f v [] = v
foldr f v (x:xs) = f x (foldr f v xs)
Thus, foldr (+) 0 [1,2,3,4] = sum [1,2,3,4] = 10.
My question is: can I just change it to something like :
foldr :: (a->a->a)->a->[a]->a
OR:
foldr :: (a->b->c)->x->[y]->z
I didn't find a place to explain the choice/requirements of letters in the definition. Thanks!
Update:
I tested it with:
foldr :: (a->b->c)->x->[y]->z
Got the following err:
Couldn't match type `y' with `a'
`y' is a rigid type variable bound by
the type signature for folderr :: (a -> b -> c) -> x -> [y] -> z
at test.hs:3:1
`a' is a rigid type variable bound by
the type signature for folderr :: (a -> b -> c) -> x -> [y] -> z
at test.hs:3:1
If changed everything to a, it works. I must have missing some points here.
As explained in #sepp2k's comments. I tested using the following simple example:
folderr :: (a->b->b)->b->[a]->b
folderr f v [] = v
folderr f v (x:xs) = f x (folderr f v xs)
myop :: Int -> Bool -> Bool
myop x y | x > 0 = True && y
| otherwise = False && y
folderr (myop) True [3,3,222] -> True
folderr (myop) True [3,2,-1] -> False
So a,b just means the types are different or not.
The specific names of your type variables do not matter, that is the types a -> b -> c, x -> y -> z and foo -> bar -> baz are all completely equivalent.
What does matter is whether you use the same type variable multiple times or you use different ones. That is a -> b is a different type than a -> a. Specifically a -> b is more general because out of the concrete types Int -> Int, String -> String, Int -> String and String -> Int, a -> a would only match the first two (with a = Int and a = String respectively) whereas a -> b would match all four.

Can mapEvery be implemented with foldr

For a function that maps a function to every nth element in a list:
mapEvery :: Int -> (a -> a) -> [a] -> [a]
mapEvery n f = zipWith ($) (drop 1 . cycle . take n $ f : repeat id)
Is it possible to implement this with foldr like ordinary map?
EDIT: In the title, changed 'folder' to 'foldr'. Autocorrect...
Here's one solution
mapEvery :: Int -> (a -> a) -> [a] -> [a]
mapEvery n f as = foldr go (const []) as 1 where
go a as m
| m == n = f a : as 1
| otherwise = a : as (m+1)
This uses the "foldl as foldr" trick to pass state from the left to the right along the list as you fold. Essentially, if we read the type of foldr as (a -> r -> r) -> r -> [a] -> r then we instantiate r as Int -> [a] where the passed integer is the current number of elements we've passed without calling the function.
Yes, it can:
mapEvery :: Int -> (a -> a) -> [a] -> [a]
mapEvery n f xs
= foldr (\y ys -> g y : ys) []
$ zip [1..] xs
where
g (i, y) = if i `mod` n == 0 then f y else y
And since it's possible to implement zip in terms of foldr, you could get even more fold-y if you really wanted. This even works on infinite lists:
> take 20 $ mapEvery 5 (+1) $ repeat 1
[1,1,1,1,2,1,1,1,1,2,1,1,1,1,2,1,1,1,1,2]
This is what it looks like with even more foldr and inlining g:
mapEvery :: Int -> (a -> a) -> [a] -> [a]
mapEvery _ _ [] = []
mapEvery n f xs
= foldr (\(i, y) ys -> (if i `mod` n == 0 then f y else y) : ys) []
$ foldr step (const []) [1..] xs
where
step _ _ [] = []
step x zipsfn (y:ys) = (x, y) : zipsfn ys
Now, would I recommend writing it this way? Absolutely not. This is about as obfuscated as you can get while still writing "readable" code. But it does demonstrate that this is possible to use the very powerful foldr to implement relatively complex functions.

Resources