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?
TLDR; Don't use the undefined primitive. It's a value that the JS compiler will automatically set for you when you declare variables without assignment or if you try to access properties of objects for which there is no reference.
You can define something as undefined. var a= undefined . You can pass fn(undefined) . If you want to find the difference between an undefined property p of an object o , and a property p that has defined and set to undefined , you have to use the 'p' in o operator.
Both undefined and null are falsy by default. So == returns true. But when we use the strict equality operator (===) which checks both type and value, since undefined and null are of different types (from the typeof Operator section), the strict equality operator returns false.
In JavaScript, they both are related to memory space and there is a very simple difference between them. If the variable name which is being accessed doesn't exist in memory space then it would be not defined, and if exists in memory space but hasn't been assigned any value till now, then it would be undefined.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With