我有一个任何类型的值(或函数)列表。我有另一个类型的功能列表。运行时的用户将从第一个列表中选择一个,从第二个列表中选择另一个。我有一个机制来确保这两个项是类型兼容的(第一个值或输出与第二个输入兼容)。
我需要一些方法来用函数调用函数(或组合函数)。如果第二个函数具有具体类型,则unsafeCoerce工作正常。但如果形式如下:
polyFunc :: MyTypeclass a => a -> IO ()
polyFunc x = print . show . typeclassFunc x
然后unsafeCoerce不起作用,因为它无法解析为具体类型。
有什么办法可以做我想做的事吗?
这是列表可能的样子。但是......我不仅限于此,如果有其他方式来代表这些将解决问题,我想知道。需要考虑的一个关键事项是:列表可以在运行时更改,因此我不知道在编译时可能涉及的所有可能类型。
data Wrapper = forall a. Wrapper a
firstList :: [Wrapper]
firstList = [Wrapper "blue", Wrapper 5, Wrapper valueOfMyTypeclass]
data OtherWrapper = forall a. Wrapper (a -> IO ())
secondList :: [OtherWrapper]
secondList = [OtherWrapper print, OtherWrapper polyFunc]
注意:至于我为什么要做这样疯狂的事情: 我正在生成代码并使用提示进行类型检查。但这发生在运行时。问题是提示在实际执行时速度很慢,而高性能对此至关重要。此外,至少在某些情况下,我不想生成代码并在运行时通过ghc运行它(尽管我们也做了一些)。所以...我正试图找到中间的某个地方:动态地将事物连接在一起而不必生成代码和编译,但是以编译速度运行而不是解释。
答案 0 :(得分:3)
编辑:好的,现在我看到了更多内容,这是一个非常通用的方法 - 不要直接使用多态函数!相反,使用Dynamic -> IO ()
类型的函数!然后,他们可以直接使用“typecase”式调度来选择调用哪个单态函数 - 即只需打开TypeRep。你做必须直接为你正在包装的每个多态函数编码这个调度。但是,如果它变得足够麻烦,你可以使用一些模板Haskell自动执行此操作。
基本上,正如Dynamic
在静态类型语言中嵌入动态类型语言一样,而不是重载Haskell的多态性,现在将其扩展为 embed 动态静态类型语言中的多态性。
-
旧答案:更多代码会有所帮助。但是,据我所知,这是读/显问题。即你有一个产生多态结果的函数,以及一个带有多态输入的函数。问题是你需要选择中间值是什么,以便它满足两个约束。如果你有一个机制这样做,那么通常的技巧将起作用,确保你满足编译器无法知道答案的那个开放式问题。
答案 1 :(得分:1)
我不确定我完全理解你的问题。但是,由于您具有兼容类型的价值和功能,您可以将它们组合成单个值。然后编译器可以证明类型匹配。
{-# LANGUAGE ExistentialQuantification #-}
data Vault = forall a . Vault (a -> IO ()) a
runVault :: Vault -> IO ()
runVault (Vault f x) = f xrun