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

    or Bool

    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?

+3


source to share


2 answers


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]

      

+4


source


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.

+4


source







All Articles