Haskell多态函数在代数数据类型之间进行转换

Paa*_*yim 7 haskell types function

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

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
Run Code Online (Sandbox Code Playgroud)

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

foo A = C
foo B = D
foo C = A
foo D = B
Run Code Online (Sandbox Code Playgroud)

但是Haskell从"foo A = C"推断出函数是

foo :: Ab -> Cd
Run Code Online (Sandbox Code Playgroud)

我试图使类的数据类型实例使foo变形,但它不起作用.

class Abcd a
instance Abcd Ab
instance Abcd Cd

foo :: Abcd a => a -> Ab
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

jbe*_*man 14

这很自然TypeFamilies.您定义了一个类型级函数

type family Converted a
type instance Converted Ab = Cd
type instance Converted Cd = Ab
Run Code Online (Sandbox Code Playgroud)

然后你的签名变成了

foo :: a -> Converted a
Run Code Online (Sandbox Code Playgroud)

如果你只是在摆弄你要完成的类型,但由于你想在价值层面上有不同的行为(A从a C等返回),我们实际上需要在新类型的实例之间传播我们的案例:

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
Run Code Online (Sandbox Code Playgroud)

(现场演示)

最后,Converted如果使用最近的GHC ,您可以考虑创建一个封闭类型的同义词系列,或者通过移动Convertable实例声明中的实例使其"关联" .