Why does the following code not compile even if I added the Typeable
boundary to satisfy the cast
function's requirements?
import Data.Data
a :: Maybe Int
a = cast f
where
f :: Typeable a => a
f = undefined
app/Main.hs:6:5: error:
• No instance for (Typeable a0) arising from a use of ‘cast’
• In the expression: cast f
In an equation for ‘a’:
a = cast f
where
f :: Typeable a => a
f = undefined
|
6 | a = cast f
| ^^^^
Maybe Int
should implement the type class because the following code compiles.
import Data.Data
b :: String
b = show $ typeRep (Proxy :: Proxy (Maybe Int))
(I'm not asking how to cast a value, e.g., from Int
to String
. I'm just curious about this strange error.)
GHC: 9.2.2
CodePudding user response:
The problem is that you never specify the type that f
should have before the cast. You could equally well do
a :: Maybe Int
a = cast (f :: Int)
where f :: Typeable a => a
f = undefined
(which would yield Just ⊥
) or
a :: Maybe Int
a = cast (f :: [String])
where f :: Typeable a => a
f = undefined
(which would yield Nothing
).
Some constraints would cause the compiler to default an unspecified type, e.g. a Num
context would default to Integer
. But Typeable
does not default to anything, so the compiler baulks.
CodePudding user response:
When you write a polymorphic declaration like that you are basically saying i can produce any a
that has a Typeable
instance. Then the caller decides which a
to instantiate the type variable. For example
b :: String
b = show f
where
f :: (Show a) => a
f = undefined -- for example you cannot write f="x"
this produces a similar error. It is not specified anywhere in the program what a
should be used.