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 运行时检查,这将为您提供一些不错的类型检查支持)并且基本上有两种方法可以做到(我知道)
  • Type Families 我给你看的
  • functional dependencies 仙人掌做的

  • 两者都为您(以及其他人)提供了某种方式来表达的方法:看看我是否得到类型 A 我可以说出某些关联类型 B 必须是什么( Foo -> IntBar -> String )

    这是一个很深的话题(边界依赖类型;))但我认为带有类的类型族并不难理解。

    我使用的想法是让类 PolyMap 提供 polyMap 函数(您可以将它命名为任何您想要的名称 - doSomething ,无论如何),并且输出类型取决于使用 To k 映射的输入类型,该映射是 IntFooString对于 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/

    10-14 16:44
    查看更多