2013-12-20 61 views
1

可以在haskell中继承数据类型吗?让我们假设:在Haskell中继承数据类型?

data Data1 = Data1 
    { name :: String 
    } deriving (Show) 

在同一个模块,我想要做的事,如:

data Data2 = Data1 
let x = Data2 "Something" 

我希望Data2有场name,从Data1 '继承'。我知道data Data2 = Data1不这样做。所以,我想知道是否有办法做到这一点。

感谢

安德烈

+0

我只想指出[乙烯](https://github.com/VinylRecords/Vinyl/blob/master/Data/Vinyl/Relation.hs)记录确实有这样的事情。 – phg

回答

5

Haskell没有继承。事实上,消除你脑海中所有与OOP有关的想法。

相反,从构图的角度来看是一个更有成效的方法。

newtype Data1 = Data1 {name :: String} 
       deriving Show 

newtype Data2 = Data2 {wrappedD1 :: String} 

现在你可以有

nameD2 :: Data2 -> String 
nameD2 = name . wrappedD1 

但是,如果你想使用相同的名称为这两项操作,你会想“特设多态”又名超载。在Haskell的土地,我们有这个

data D1 = D1 {nameD1 :: String} deriving Show 
data D2 = D2 {wrappedD1 :: D1} deriving Show 

class Named a where 
    name :: a -> String 

instance Named Data1 where 
name = nameD1 
instance Named Data2 where 
    name = name . wrappedD1 

类型类现在,我们可以在两个D1D2使用name。这与接口的概念相似。

切线:您使用顶级语法let foo = bar,但在Haskell中,由于GHCi的工作原理奇怪,我们只在GHCi中使用let绑定。请使用foo = bar

+0

顺便说一句,为什么“消除所有OOP相关的想法”?在我看来,考虑接口类型(在OOP意义上)可以帮助OOP头适应:) – 9000

+5

@ 9000我更多地说这是因为试图编写围绕子类型层次结构的Java代码会导致无法读取/效率低下哈斯克尔。类型<=>接口是一个有用的比喻,但是和所有的类比一样,它最终会失败。考虑多参数类型的类,输入类型不作为第一个参数和类似的类 – jozefg

2

哈斯克尔趋于结构性亚型和 “HAS-A” 关系做好。继承数据1的最直接的方法是使用newtype

newtype Data2 = Data2 { unData2 :: Data1 } 

在这种情况下Data2被称为是相同Data1。实际上,在编译时Data2将与Data1相同。重要的是Data2将有机会定义完全唯一的类型instances如果它选择。

除此之外,您可以在一些更复杂的“继承”数据类型中创建Data1记录。

data DataMore = 
    DataMore { data1   :: Data1 
      , otherThing :: OtherThing 
      , somethingElse :: SomethingElse 
      } 

现在,任何需要Data1作为参数能够被平凡扩展采取DataMore!而非。

-- given... 
foo :: Data1 -> Data1 -> X 

-- we have 
fooMore :: DataMore -> DataMore -> X 
fooMore dm1 dm2 = foo (data1 dm1) (data1 dm2) 

这是一种逆变分型。

+2

虽然我明白你在说什么,但是你的措辞有点危险。 Haskell没有子类型(结构,逆变或其他类型)。 –

+1

我同意你在技术性方面的批评,但是发现有一个有意义的论点可以解释上面发生的“一种”“继承”。不过,我对这个术语没有任何依恋。我只是觉得它在教学上很有用。 –