Search code examples
haskellpolymorphismgadtexistential-type

Functions to Polymorphic data types


data Foo a is defined like:

data Foo a where
  Foo :: (Typeable a, Show a) => a -> Foo a
  -- perhaps more constructors

instance Show a => Show (Foo a) where
  show (Foo a) = show a

with some instances:

fiveFoo :: Foo Int
fiveFoo = Foo 5

falseFoo :: Foo Bool
falseFoo = Foo False

How can I define any function from b -> Foo a, for example:

getFoo :: (Show a, Typeable a) => String -> Foo a
getFoo "five" = fiveFoo
getFoo "false" = falseFoo

Here getFoo does not type check with Couldn't match type ‘a’ with ‘Bool’.

The only thing that I am interested in here is for a to be of class Showso I can use getFoo like:

main = getLine >>= (print . getFoo)

Solution

  • Perhaps you want to omit the type parameter from Foo.

    data Foo where
      Foo :: (Typeable a, Show a) => a -> Foo
    
    instance Show Foo where
      show (Foo a) = show a
    
    fiveFoo :: Foo
    fiveFoo = Foo (5 :: Int) -- (Foo 5) doesn't work because of ambiguity
    
    falseFoo :: Foo
    falseFoo = Foo False
    
    getFoo :: String -> Foo
    getFoo "five" = fiveFoo
    getFoo "false" = falseFoo
    
    print $ getFoo "five" -- prints '5'
    print $ getFoo "false" -- prints 'False'