John Walters
John Walters

Reputation: 113

How do I implement this function without using mixed lists?

Let's say I have a function that takes a list of function-list pairs, and maps the function in each pair onto the list in the pair, for example:

myFunction [("SOME"++,["DAY","ONE"]), (show,[1,2])] == [["SOMEDAY", "SOMEONE"],["1","2"]]

Is there a way of implementing myFunction so that the code I provided above will work as is without any modifications?

My problem is I can't figure out how to implement myFunction because the types of each sub-list could be different (in my example I have a list of strings ["DAY", ONE"], and a list of numbers: [1,2]). I know that each function in the list will convert its list into a list of strings (so the final list will have type [[Char]]), but I don't know how to express this in Haskell.

Upvotes: 3

Views: 155

Answers (2)

Chris Taylor
Chris Taylor

Reputation: 47392

You want to use existential quantification to define a type that can hold any value as long as it is a member of the Show typeclass. For example:

{-# LANGUAGE ExistentialQuantification #-}

data S = forall a. Show a => S a

instance Show S where
    show (S s) = show s

f :: [S] -> [String]
f xs = map show xs

And now in ghci:

*Main> f [S 1, S True, S 'c']
["1","True","'c'"]

You won't be able to run the code in your question without modification, because it contains a heterogeneous list, which the Haskell type system forbids. Instead you can wrap heterogeneous types up as a variant type (if you know in advance all the types that will be required) or as an existentially quantified type (if you don't know what types will be required, but you do know a property that they must satisfy).

Upvotes: 1

Don Stewart
Don Stewart

Reputation: 137977

You can do it with existential types

{-# LANGUAGE ExistentialQuantification #-}

data T = forall a b. Show b => (:?:) (a -> b) [a]

table =
    [ ("SOME"++) :?: ["DAY","ONE"]
    , (show)     :?: [1,2]
    , (+1)       :?: [2.9, pi]
    ]

And run it as:

apply :: T -> String
apply (f :?: xs) = show $ map f xs

main = print $ map apply table

Upvotes: 4

Related Questions