If I have this insert function:
insert x [] = [x]
insert x (h:t)
| x <= h = x:(h:t)
| otherwise = h:(insert x t)
this produces a sorted list:
foldr insert [] [1,19,-2,7,43]
but this:
foldr1 insert [1,19,-2,7,43]
produces ' cannot construct the infinite type: a0 = [a0] '
I'm confused about why the second call cannot work.
I have looked at the definitions for both foldr and foldr1 and have traced both with simple arithmetic functions, but I still cannot come up with a clear explanation for why the second call fails.
Let's look at some type signatures.
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr1 :: (a -> a -> a) -> [a] -> a
In both cases, the first argument is a function of two arguments.
foldr1
, these two arguments must have the same type (and the result has this type also) foldr
, these two arguments may have different types (and the result has the same type as the second argument) What's the type of your insert
?
I like the type-based answers given here, but I also want to give an operational one explaining why we don't want this to typecheck. Let's take the source of foldr1
to start with:
foldr1 :: (a -> a -> a) -> [a] -> a
foldr1 _ [x] = x
foldr1 f (x:xs) = f x (foldr1 f xs)
Now, let's try running your program.
foldr1 insert [1,19,-2,7,43]
= { list syntax }
foldr1 insert (1:[19,-2,7,43])
= { definition of foldr1 }
insert 1 (foldr1 insert [19,-2,7,43])
= { three copies of the above two steps }
insert 1 (insert 19 (insert (-2) (insert 7 (foldr1 insert [43]))))
= { definition of foldr1 }
insert 1 (insert 19 (insert (-2) (insert 7 43)))
...whoops! That insert 7 43
is never going to work. =)
The type of foldr1
is (a -> a -> a) -> [a] -> a
, ie arguments and result of this function have the same type. However, insert
has type Ord a => a -> [a] -> [a]
. For foldr1 insert
being well-typed, a
and [a]
must be the same type.
But this would mean that a == [a] == [[a]] == [[[a]]] == ...
, ie, a
being a type of infinitely many lists.
Because foldr1
is trying to do this:
insert 43 -7
which will fail.
The problem is following:
foldr
would do this way:
insert 43 []
insert 7 result
This clearly works.
Whereas foldr1
would try to do the following:
insert 7 43
insert -2 result
which is definitely wrong. You can see, foldr1
requires the arguments to the operation to be of the same type, which is not the case for insert
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.