haskell多态类型函数

时间:2015-11-25 06:24:49

标签: haskell types polymorphism parametric-polymorphism

在Haskell中是否可以使用一个可以采用多态类型并返回多态类型的函数?

例如,我想要一个接受值的函数,如果值为mailchimp,则返回一个Int,如果类型为Foo,则返回一个字符串

Bar

这样的事情可能吗?如果没有,基于类型路由到另一个函数的最佳实践是什么?

2 个答案:

答案 0 :(得分:5)

首先你描述的内容和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开箱即用,这将为您提供一些不错的类型检查支持)并且基本上有两种方法(我知道)

两者都为你(以及其他人)提供了一些方法可以说:看看我是否得到类型AI可以说出某些相关类型B必须是什么(Foo -> IntBar -> String

这是一个很深层次的主题(borderline dependent-types;))但我认为带类的类型系列并不难理解。

我使用的想法是让类PolyMap提供polyMap函数(你可以将它命名为你想要的任何东西 - doSomething,无论如何)并且输出类型取决于输入类型使用To k映射,IntFooStringBar,如实例声明中所述。

另一个让你签名更容易:

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"

答案 1 :(得分:3)

您可以将doSomething置于以域和codomain类型为键的类型类中,并具有从域到codomain的功能依赖性:

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
{-# LANGUAGE FlexibleInstances  #-} -- if one of your `to` really is `String`
class DoSomething from to | from -> to where
    doSomething :: from -> to

instance DoSomething Foo Int where -- ...
instance DoSomething Bar String where -- ...

与基于类型族的解决方案相比,这样做的好处是如果codomain也唯一地确定了域,则可以添加另一个函数依赖项to -> from。我不认为类型系列提供了一种很好的建模方法。