I'm new to Haskell and reading Haskell from first principles.
BTW this question is general not related to this book, I have taken following question as example
In Chapter 10, Section 10.5, Q 5, part f
Question:
The following are simple folds very similar to what you’ve already seen, but each has at least one error. Please fix them and test in your REPL
f) foldr const 'a' [1..5]
and its giving this following Error
No instance for (Num Char) arising from the literal `1'
simply means that 1 can not be used as Char here
but I read in this chapter that folds are Like Text Rewriter, replace cons(:) with the function and replace empty list with Accumulator so the result is (I have shorten the list)
foldr const 'a' [1..2]
to
(1 `const` (2 `const` 'a'))
and its working no complier error
So what could went wrong ? why first one is not working and its rewritten is working ?
but I'm seeing in rewritten form const
has two forms
Int -> Int -> Int
and
Int -> Char -> Int
maybe this is bcs of it so I Fix the type of const
like this
cont :: Int -> Int -> Int
cont = const
and now When I stated using it
(1 `cont` (2 `cont` 'a'))
Couldn't match expected type `Int' with actual type `Char'
Seems like When We are using Polymorphic functions Haskell fix it type, and we can not use it in other form
maybe it should be list folds description should be like this
folds are Like Text Rewriter, replace cons(:) with the function, fix the type of function and replace empty list with Accumulator
Please share your thought about it.
not only Haskell but other typed languages has same behavior ?
or maybe I'm totally wrong ?
Your analysis is correct, though it's a bit down in the details. You can see the problem at a bit higher level, if you like.
(Forgive me if I've picked different type variables than you're used to - alpha equivalence says the variable names don't matter and keeping names different makes it easier to see what's going on.)
If you use those types and unify things to make
foldr const
work, you get something like this:Where ~ means "these types are the same".
So you can see just from
foldr
andconst
the the type of the elements of the list must unify with the type of the other argument.You are correct, though, that if the
foldr
there was inlined in its entirety before type checking, the resulting expression would check successfully. But that's a bit of an insufficient situation. What if you didfoldr const 'a' []
? Since that would reduce to'a'
, it would also type check - but it would do so with a different type than if the list passed to it was non-empty.And that's exactly the kind of problem the Haskell type system is intended to prevent. An expression's type should be derived entirely from the types of its subexpressions. Values should never(*) be considered, so an expression needs to have the same result type regardless if whether a subexpression is an empty list or non-empty.
(*) Ok, GHC supports a bit more than Haskell 2010. Extensions like GADTs can enable a form of types depending on values, but only in very specific ways that maintain larger coherent properties.