Haskell 中是否有可能有一个函数可以接受一个多态类型并返回一个多态类型?
例如,我想要一个函数,它接受一个值,如果该值是 Foo
类型,则返回一个 Int,如果它是 Bar
类型,则返回一个 String
data Foo = One | Two | Three deriving (Show, Read)
data Bar = This | That | TheOther deriving (Show, Read)
doSomething :: Either Foo Bar -> Either Int String
doSomething var = if (typeOf var) == Int then 123 else "string"
这样的事情可能吗?如果不是,根据类型路由到另一个功能的最佳做法是什么?
最佳答案
首先,您描述的内容和 Either Int String
签名似乎不匹配-我将首先尝试您描述的内容(通过输入类型选择输出类型):
你可以做一些与我认为你正在尝试使用类型族非常相似的事情:
{-# LANGUAGE TypeFamilies #-}
module SO where
data Foo = One | Two | Three deriving (Show, Read)
data Bar = This | That | TheOther deriving (Show, Read)
class PolyMap k where
type To k :: *
polyMap :: k -> To k
instance PolyMap Foo where
type To Foo = Int
polyMap _ = 123
instance PolyMap Bar where
type To Bar = String
polyMap _ = "string"
例子:
λ> polyMap One
123
λ> polyMap That
"string"
一些解释
我认为您想要的是类型映射/函数(没有开箱即用的
typeOf
运行时检查,这将为您提供一些不错的类型检查支持)并且基本上有两种方法可以做到(我知道)两者都为您(以及其他人)提供了某种方式来表达的方法:看看我是否得到类型 A 我可以说出某些关联类型 B 必须是什么(
Foo -> Int
和 Bar -> String
)这是一个很深的话题(边界依赖类型;))但我认为带有类的类型族并不难理解。
我使用的想法是让类
PolyMap
提供 polyMap
函数(您可以将它命名为任何您想要的名称 - doSomething
,无论如何),并且输出类型取决于使用 To k
映射的输入类型,该映射是 Int
和 Foo
的 String
对于 Bar
如实例声明中所述。您签名的另一个更容易:
doSomething :: Either Foo Bar -> Either Int String
doSomething (Left _) = Left 123
doSomething (Right _) = Right "string"
例子:
λ> doSomething (Left One)
Left 123
λ> doSomething (Right That)
Right "string"
关于haskell 多态类型函数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33909773/