I thought I could always put undefined
in same place where I don't know yet what to put, and the code should compile fine, the error happening at run time only if that undefined
is actually eveluated.
However, just in doing so I started writing something like
f = foldl undefined undefined undefined
in a file, and GHCi gives this error when I try to load the file
source.hs:3:7: error:
• Ambiguous type variable ‘t0’ arising from a use of ‘foldl’
prevents the constraint ‘(Foldable t0)’ from being solved.
Probable fix: use a type annotation to specify what ‘t0’ should be.
These potential instances exist:
instance Foldable (Either a) -- Defined in ‘Data.Foldable’
instance Foldable Maybe -- Defined in ‘Data.Foldable’
instance Foldable ((,) a) -- Defined in ‘Data.Foldable’
...plus one other
...plus 29 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the expression: foldl undefined undefined undefined
In an equation for ‘f’: f = foldl undefined undefined undefined
|
3 | f = foldl undefined undefined undefined
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Which I interpret as "undefined
does not typecheck here".
What is the rational behind this behavior, and what are the places where I cannot use undefined
as a temporary placeholder?
The interpreter does not know what type for f
in foldl :: Foldable f => (a -> b -> a) -> a -> f b -> a
to use, hence the error. This is important since the f
here decides exactly what implementation for foldl
it will use. Indeed for a f ~ Maybe
the implementation can be different than for an f ~ []
, so depending on the type for f
, a different foldl
is used.
If we specify the type, for example with [Int]
, or Maybe Char
, this works (well it will raise an error, but this is because the undefined
will of course not evaluate properly):
Prelude> foldl undefined undefined (undefined :: Maybe Char)
*** Exception: Prelude.undefined
CallStack (from HasCallStack):
error, called at libraries/base/GHC/Err.hs:78:14 in base:GHC.Err
undefined, called at <interactive>:1:6 in interactive:Ghci1
Prelude> foldl undefined undefined (undefined :: [Int])
*** Exception: Prelude.undefined
CallStack (from HasCallStack):
error, called at libraries/base/GHC/Err.hs:78:14 in base:GHC.Err
undefined, called at <interactive>:2:6 in interactive:Ghci1
For certain type classes like Num
, there is type defaulting [Wkang's Haskell; blog]. This uses:
default Num Integer default Real Integer default Enum Integer default Integral Integer default Fractional Double default RealFrac Double default Floating Double default RealFloat Double