Haskell 如何在不使用混合列表的情况下实现此函数?

Haskell 如何在不使用混合列表的情况下实现此函数?,haskell,types,existential-type,Haskell,Types,Existential Type,假设我有一个函数,它获取函数列表对的列表,并将每对中的函数映射到该对中的列表,例如: myFunction [("SOME"++,["DAY","ONE"]), (show,[1,2])] == [["SOMEDAY", "SOMEONE"],["1","2"]] {-# LANGUAGE ExistentialQuantification #-} data S = forall a. Show a => S a instance Show S where show (S s

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

myFunction [("SOME"++,["DAY","ONE"]), (show,[1,2])] == [["SOMEDAY", "SOMEONE"],["1","2"]]
{-# 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
有没有一种方法可以实现myFunction,这样我上面提供的代码就可以在没有任何修改的情况下正常工作


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

你可以用存在类型来表达

{-# 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
您希望使用存在量化来定义一个类型,该类型可以保存任何值,只要它是
Show
typeclass的成员。例如:

myFunction [("SOME"++,["DAY","ONE"]), (show,[1,2])] == [["SOMEDAY", "SOMEONE"],["1","2"]]
{-# 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类型系统禁止的异构列表。相反,您可以将异构类型包装为变体类型(如果您事先知道所有需要的类型)或存在量化类型(如果您不知道需要什么类型,但您知道它们必须满足的属性)。

您不能“按原样”,因为参数列表本身已经不会进行类型检查。最接近的答案是使用存在类型。但在95%的情况下,这个问题实际上是选择了错误的设计。所以让我问一下,为什么要这样做?很抱歉“按原样”的问题我可能应该更清楚地表达自己,我只是想避免像“生成数据类型a=Int | String,并将其用作包装器”这样的解决方案,应该给出最接近的答案。至于我想做什么,下面是一个更接近我真实代码的示例。我有一个函数openURLs,它获取URL列表。我还有两个列表l1=[“谷歌”、“维基百科”]、l2=[(“谷歌”、“斑马”)、(“维基百科”、“老虎”)],我还有函数f1和f2,f1将把与l1类型相同的列表转换为URL列表,f2用于l2类型的列表。