如何在不使用混合列表的情况下实现此功能?

时间:2012-05-11 12:24:42

标签: haskell types existential-type

假设我有一个函数,它接受函数列表对的列表,并将每对中的函数映射到对中的列表中,例如:

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

有没有办法实现myFunction,以便我上面提供的代码可以正常工作而不做任何修改?

我的问题是我无法弄清楚如何实现myFunction,因为每个子列表的类型可能不同(在我的例子中我有一个字符串列表[“DAY”,ONE“]和一个列表数字:[1,2])。我知道列表中的每个函数都会将其列表转换为字符串列表(因此最终列表将具有类型[[Char]]),但我不知道如何表达这在Haskell。

2 个答案:

答案 0 :(得分:4)

你可以用存在类型

来做
{-# LANGUAGE ExistentialQuantification #-}

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

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

并按以下方式运行:

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

main = print $ map apply table

答案 1 :(得分:1)

您希望使用存在量化来定义可以包含任何值的类型,只要它是Show类型类的成员即可。例如:

{-# 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

现在在ghci:

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

如果没有修改,您将无法在您的问题中运行代码,因为它包含异构列表,Haskell类型系统禁止该列表。相反,您可以将异构类型包装为变体类型(如果您事先知道将需要的所有类型)或作为存在量化类型(如果您不知道将需要哪些类型,但您确实知道属性)他们必须满足。)