snøreven
snøreven

Reputation: 1974

Let function return arbitrary instances of type

I want a function to be able to return all possible instances (not sure if that's the right word) of a type. Like this (fun not working):

data T a where
    TInt :: Int -> T Int
    TStr :: String -> T String

fun :: Int -> T (forall a. a)
fun a | a >= 5    = TStr "a lot"
      | otherwise = TInt a

My end goal is to have an alias type SomeT that stands for arbitrary T.

I want to use this to parse type declarations of a DSL. I have int and string types and want to have one parsing function that parses them all.

Is this possible?

Upvotes: 1

Views: 80

Answers (2)

chi
chi

Reputation: 116174

You could use an existential type wrapper.

data T a where
    TInt :: Int -> T Int
    TStr :: String -> T String

data SomeT where
    S :: T a -> SomeT

fun :: Int -> SomeT
fun a | a >= 5    = S $ TStr "a lot"
      | otherwise = S $ TInt a

foo :: SomeT -> Maybe (T Int)
foo (S x@(TInt _)) = Just x
foo _              = Nothing

Upvotes: 3

lisyarus
lisyarus

Reputation: 15568

The usual solution to this are simply algebraic data types.

data T = TInt Int | TStr String

fun :: Int -> T
fun a | a >= 5   = TStr "a lot"
      | othrwise = TInt a

However, your exact problem can be solved, using typeclasses for ad-hoc polymorphic behavior:

class TT a where
    tt :: a -> T a

instance TT Int where
    tt = TInt

instance TT String where
    tt = TString

fun :: (TT a) => Int -> T a
fun a | a >= 5    = tt "a lot"
      | otherwise = tt a

Upvotes: 0

Related Questions