I’m trying to get the following code to compile
import IO
data MyInt = MyInt Int
data MyString = MyString String deriving Show
class Show b => MyClass a b where
fn :: a -> b
instance MyClass MyInt MyString where
fn (MyInt i) = MyString (show i)
myprint :: (MyClass a b) => a -> IO ()
myprint a = putStrLn $ show (fn a)
main = myprint (MyInt 3)
with ghc Main.hs -XMultiParamTypeClasses. However, the compiler cannot deduce the type of the b type variable (which in this case is MyString). How can I explicitly tell this information to the compiler?
You’ve run afoul of the “open world” assumption. In this case, there’s only one instance in scope that can satisfy the type constraints; but that’s not a very declarative way to specify the meaning of
myprint 3, is it? Given that instances can float in really from any module whatsoever, we can see how the open world assumption protects you from unanticipated changes of type/behaviour as modules are added or updated.You could try functional dependencies or type families in this case.