MISTAKE. The assumed type is not general enough.
I am trying to write a simple higher order function in Haskell that takes two arguments:
- List of functions of any type.
- List (numbers or
String
orBool
ean etc.) -> any type
The function should apply all functions in the first list to all elements in the second list, store the values in the list, and return the list. Sample program:
Main> apply [(^2),(^3),(^4)] [2..8]
--result: --[4,8,9,16,25,27,32,36,49,64,81,125,128,216,256,343,512,625,1296,2401,4096]
The function type must be:
apply :: Ord u => [v->u]->[v]->[u]
For this, I used two helper functions and used recursion. My program is like this:
apply :: Ord u => [v->u]->[v]->[u]
apply p s = myApply p s [] --line 59--
myApply :: Ord u => [v->u]->[u]->[u]->[u]
myApply f_list num_list starterlist
| null f_list = starterlist
| otherwise = myApply (tail f_list) (num_list) ( applyList (head f_list) num_list starterlist )
applyList :: Ord u => (v->u)->[u]->[u]->[u]
applyList f num_list starterlist
| null num_list = starterlist
| otherwise = applyList f (tail num_list) ( (head num_list) : starterlist )
I am getting the error:
ERROR "Lab2.hs":59 - Inferred type is not general enough
*** Expression : applyList
*** Expected type : Ord a => (b -> a) -> [a] -> [b] -> [a]
*** Inferred type : Ord a => (a -> a) -> [a] -> [a] -> [a]
Any idea what's wrong with types?
source to share
The reason you are getting this error is because there are conflicting signature types :
apply :: Ord u => [v->u]->[v]->[u]
apply p s = myApply p s [] --line 59--
myApply :: Ord u => [v->u]->[u]->[u]->[u]
myApply f_list num_list starterlist
| null f_list = starterlist
| otherwise = myApply (tail f_list) (num_list) ( applyList (head f_list) num_list starterlist )
As you can see, the function apply
calls the function immediately myApply
. Since it myApply
has a signature [v -> u] -> [u] -> [u] -> [u]
, it means that it apply
can only have a signature [v->u] -> [u] -> [u]
.
Quick fix: to generalize how myApply
and myApplyList
on [v -> u] -> [v] -> [u] -> [u]
. Now compile and an error is detected, you are committed to its function applyList
: you forgot to call f
on head num_list
. So you can fix this and get the following code:
apply :: Ord u => [v->u]->[v]->[u]
apply p s = myApply p s [] --line 59--
myApply :: Ord u => [v->u]->[v]->[u]->[u]
myApply f_list num_list starterlist
| null f_list = starterlist
| otherwise = myApply (tail f_list) (num_list) ( applyList (head f_list) num_list starterlist )
applyList :: Ord u => (v->u)->[v]->[u]->[u]
applyList f num_list starterlist
| null num_list = starterlist
| otherwise = applyList f (tail num_list) ( (f (head num_list)) : starterlist )
However, this code is rather fuzzy and uses a method for many functions and arguments. You can replace it entirely with a single list comprehension:
apply :: [v -> u] -> [v] -> [u]
apply fs xs = [f x | f <- fs, x <- xs]
Based on your comment, you will also have to sort the values later in the process, you can do this using sort :: Ord a => [a] -> [a]
builtin:
-- sorting variant
apply :: Ord u => [v -> u] -> [v] -> [u]
apply fs xs = sort [f x | f <- fs, x <- xs]
This generates the required output:
Prelude Data.List> (\fs xs -> sort [f x | f <- fs, x <- xs]) [(^2),(^3),(^4)] [2..8]
[4,8,9,16,16,25,27,36,49,64,64,81,125,216,256,343,512,625,1296,2401,4096]
source to share
Variation on a theme: taking into account Willem's comment indicating that this is quite complex code (making it difficult to parse). I would start with simpler code with no types at all, in order to first get a simple working example (i.e. a function that produces the expected result) while still using a helper function and recursion:
apply fs [] = []
apply [] xs = []
apply (f:fs) xs = (helper f xs) ++ (apply fs xs)
helper f [] = []
helper f (x:xs) = f x : helper f xs
Then I would ask the Haskell compiler to give me information about what type signature it inferred:
*Main> :t apply
apply :: [t1 -> t] -> [t1] -> [t]
After understanding what t1 -> t
yours is displaying v->u
, I see that the type signature can also be written as:
[v -> u] -> [v] -> [u]
Doing similar for helper
you will get the following:
apply :: [v->u] -> [v] -> [u]
apply fs [] = []
apply [] xs = []
apply (f:fs) xs = (helper f xs) ++ (apply fs xs)
helper :: (v -> u) -> [v] -> [u]
helper f [] = []
helper f (x:xs) = f x : helper f xs
This is where you can work by adding constraint Ord
and creating sorting functions etc.
source to share