简体   繁体   English

haskell多态类型函数

[英]haskell polymorphic type functions

Is it possible in Haskell to have a function that can take a polymorphic type and return a polymorphic type? 在Haskell中有可能有一个可以采用多态类型并返回多态类型的函数吗?

For example, I want a function that takes a value, and returns an Int if the value is of type Foo and a String if it is of type Bar 例如,我想要一个获取值的函数,如果值是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"

Is something like this possible? 这样的事情可能吗? If not, what is the best practice for routing to another function based on type? 如果没有,基于类型路由到另一个函数的最佳实践是什么?

first the things you describe and the Either Int String signature seem not to match - I'll try what you describe first (choose the output-type by it's input type): 首先你描述的东西和Either Int String签名似乎不匹配 - 我会先尝试你描述的内容(按输入类型选择输出类型):

you can do something very similar to what I think you are trying with type-families: 你可以做一些非常类似于我认为你尝试使用类型系列的东西:

{-# 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"

example: 例:

λ> polyMap One
123
λ> polyMap That
"string"

some explanation 一些解释

What I think you want is to have type-mappings/functions (there is no runtime check with typeOf out-of-the box and this would give you some nice type-checking support instead) and there are basically two ways to do it (I am aware of) 我认为你想要的是具有类型映射/函数(没有运行时检查与typeOf开箱即用,这将为你提供一些很好的类型检查支持),基本上有两种方法(我知道)

Both give you (among others) the means to have some way to say: look if I get type AI can say what some associated type B must be ( Foo -> Int and Bar -> String ) 两者都给你(以及其他)有一些方法可以说:看看我是否得到类型AI可以说一些相关类型B必须是什么( Foo -> IntBar -> String

This is a deep topic (borderline dependent-types ;)) but I think type-families with classes are not to hard to understand. 这是一个深层主题(borderline dependent-types;))但我认为带类的类型系列并不难理解。

The idea I used is to have the class PolyMap that provides the polyMap function (you can have it named anything you want - doSomething , whatever) and there the output type depends on the input type using the To k mapping which is Int for Foo and String for Bar as stated in the instance-declarations. 我以前的想法是有类PolyMap ,提供了polyMap功能(你可以把它命名为任何你想要的- doSomething ,不管),而且输出类型,使用依赖于输入型To k映射是IntFooBar String ,如实例声明中所述。


the other one for your signature is even easier: 另一个为您的签名更容易:

doSomething :: Either Foo Bar -> Either Int String
doSomething (Left _) = Left 123
doSomething (Right _) = Right "string"

example: 例:

λ> doSomething (Left One)
Left 123
λ> doSomething (Right That)
Right "string"

You can put doSomething in a typeclass keyed on both the domain and the codomain types, with a functional dependency from the domain to the codomain: 你可以将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 -- ...

Compared with the type family-based solution, this has the benefit that if the codomain also uniquely determines the domain , you can add another functional dependency to -> from . 与基于类型族的解决方案相比,这样做的好处是, 如果codomain也唯一地确定了域 ,则可以to -> from添加另一个函数依赖项。 I don't think type families offer a good way of modelling that. 我不认为类型系列提供了一种很好的建模方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM