Haskell多态函数在代数数据类型之间进行转换 [英] Haskell polymorphic function to convert between algebraic data types

查看:95
本文介绍了Haskell多态函数在代数数据类型之间进行转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个haskell函数,它们可以在两种代数数据类型之间进行转换。

  data Ab = A | B 
data Cd = C | D

from Ab :: Ab - >来自Ab的Cd
来自Ab的= B
B = D

toAb :: Cd - > Ab
toAb C = A
toAb D = B

但我想来创建一个多态函数,该函数使用代数数据类型并在它们之间进行转换。

  foo A = C 
foo B = D
foo C = A
foo D = B

但是Haskell从foo A = C推导出函数为

  foo :: Ab  - > Cd 

我试图让一个类的数据类型实例变成foo多态,但它没有

  class Abcd a 
实例Abcd Ab
实例Abcd Cd

foo :: Abcd a => a - > Ab

任何想法?

解决方案

这很自然, TypeFamilies 。您定义了一个类型级别的函数

  type family转换一个
类型的实例Converted Ab = Cd
type实例转换Cd = Ab

然后您的签名变成

  foo :: a  - >转换了

如果你只是在摆弄你要做的类型,但因为你想拥有在价值层面上的不同行为(从 C 等等返回一个 A )我们实际需要分摊我们的情况跨越新类型的实例:

  class Convertable a where 
foo :: a - >转换

实例可转换ab其中
foo A = C
foo B = D

实例可转换Cd其中
foo C = A
foo D = B

live demo



最后,您可以考虑制作 Converted 如果使用最近的GHC,则使用封闭类型同义词族,或者通过移动 Convertable 实例声明中的实例使其关联。


I have two haskell functions, which convert between two algebraic data types.

data Ab = A | B
data Cd = C | D

fromAb :: Ab -> Cd
fromAb A = C
fromAb B = D

toAb :: Cd -> Ab
toAb C = A
toAb D = B

But I would like to make a polymorph function, that takes both algebraic data types and converts between them.

foo A = C
foo B = D
foo C = A
foo D = B

But Haskell deduces from "foo A = C" that the function is

foo :: Ab -> Cd

I tried to make the data types instances of a class to make foo polymorph but it didn't work.

class Abcd a
instance Abcd Ab
instance Abcd Cd

foo :: Abcd a => a -> Ab

Any Ideas?

解决方案

This is very natural with TypeFamilies. You define a type-level function

type family Converted a
type instance Converted Ab = Cd
type instance Converted Cd = Ab

Then your signature becomes

foo :: a -> Converted a

If you just were fiddling with types you'd be done, but since you want to have different behavior on the value level (returning an A from a C and so on) we actually need to spread our cases across instances of a new type class:

class Convertable a where
    foo :: a -> Converted a

instance Convertable Ab where
    foo A = C
    foo B = D

instance Convertable Cd where
    foo C = A
    foo D = B

(live demo)

Finally, you might consider making Converted a closed type synonym family if using recent GHC, or make it "associated" by moving the instances inside the Convertable instance declarations.

这篇关于Haskell多态函数在代数数据类型之间进行转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆