I am working on a mathematics project with a persistent need of extracting a canonical "basis" out of a type, so I defined the following type class.
class Basis a where
getBasis :: Int -> [a]
And I want to use this basis in a separate function:
foo :: (Basis a) => Int -> (a -> b) -> IO ()
foo n f = do
let theBasis = getBasis n
undefined
-- Do some stuff with the basis using the function f.
-- theBasis should have type [a].
However this fails to type check, yielding an error of the form Could not deduce (Basis a0) arising from the use of 'getBasis' from the context: Basis a
.
I tried to help the typechecker by explicitly writing the expected type:
foo n f = do
let theBasis = (getBasis n) :: [a]
undefined
But the error persists, and moving the type annotation to different terms in that line does not fix the error.
How can I tell the typechecker that I want the type of getBasis n
to be the same a
appearing in the signature of foo
?
The easiest way to do this in this case would be to just use the basis for something, because then the typechecker can infer which a
you meant:
Silly example:
foo :: Basis a => Int -> (a -> b) -> IO ()
foo n f = do
let theBasis = getBasis n
_ = map f theBasis
undefined
Otherwise you can also use type annotations (requires the ScopedTypeVariables
extension, without that the a
inside the function body won't be the a
from the signature):
foo :: forall a b. Basis a => Int -> (a -> b) -> IO ()
foo n f = do
let theBasis = getBasis n :: [a]
undefined
With ScopedTypeVariables
+ TypeApplications
you can also explicitly pass the type parameter a
along to getBasis
:
foo :: forall a b. Basis a => Int -> (a -> b) -> IO ()
foo n f = do
let theBasis = getBasis @a n
undefined