[英]“Composite” algebraic data types in Scala and Haskell
当尝试在Scala中用代数数据类型描述Sql的一部分时,我遇到了创建根特征代表数据类型的子特征的必要性。 由于满足此要求产生了我不确定是否可以用Haskell的ADT表示的代码,并且由于与Haskell不同,ADT不是Scala的本机构造,所以我现在想知道:
Statement
具有构造函数Select
的模型,例如Sql
类型的模型? (似乎这可能是相关的)。 这是我正在谈论的模型:
sealed trait Sql
sealed trait Statement
extends Sql
sealed case class Union
( left : Statement,
right : Statement )
extends Statement
sealed case class Select
( /** other fields don't matter **/
where : Where )
extends Statement
sealed trait Where
extends Sql
sealed case class And
( left : Where,
right : Where )
extends Where
sealed case class Or
( left : Where,
right : Where )
extends Where
sealed case class Equals
( /** fields don't matter **/ )
extends Where
不可以,因为你根本特点是密封的,有可能代表所提出的层次结构的ADT:
data Sql = Statement Statement | Where Where
-- ^ This is the *type* called `Statement`
-- ^ This is the *constructor* called `Statement`
data Statement = Union Statement Statement | Select Where
data Where = And Where Where | Or Where Where | Equals
在这种情况下是可能的,因为您可以枚举数据类型的所有“子类”(在本例中为Sql
),从而可以将它们转换为ADT构造函数。 如果要允许用户随意添加“构造函数” /“子类”,则很难将类型层次结构模拟为ADT。
2.术语ADT永远不适用于Scala代码,因为Scala缺少该语言的ADT。 但是,您提供的类的行为类似于ADT,因此我会说“足够接近”。
3&4。这些语言有不同的优点和缺点。
Haskell可以仿真每种Scala语言功能,而Scala可以仿真每种Haskell功能,因为两种语言都已完成,并且可以使用不同级别的元编程。 Haskell当然具有模板Haskell,该模板允许进行任何模拟-您可能使用TH能够在Haskell文件中编写Scala代码并将其编译为Haskell。
Haskell不需要对象和继承,而Scala则不需要ADT,因此没有理由将两者进行比较。 大多数面向对象的功能也可以使用简单的Haskell类型类和数据类型以及使用模块边界进行仿真。 可以使用案例类在Scala中模拟ADT,而可以使用隐式参数和隐式对象实例来模拟Haskell类型类。
但是,我想说通常来说,在Haskell中模拟某些Scala功能会更容易,因为Haskell比Scala允许更多的“隐式语言扩展”。 我的意思是,如果要在Scala中模拟Haskell Monad
,则必须在使用Monad
的部分中编写大量代码,而如果要模拟Scala的定界延续或隐式参数在Haskell中,您只需为此编写一次Monad
实例(用于延续)或多参数类型类(用于隐式参数),以后您在实际函数中编写的代码看起来将非常类似于Scala代码,而无需很多锅炉板。 Scala的许多高级功能(即使不是大多数)的确也源自Haskell或OCaml,因此它们已经存在并且不需要翻译。
换句话说:添加新功能所需的复杂代码仅需在Haskell的一个位置添加,此后即可在多个位置轻松使用,而您通常必须在各处各处添加大量“噪声”如果要模拟Haskell功能,请使用Scala代码。
您可以在Haskell中模仿Scala设计,尽管Haskell鼓励使用限定类型和求和类型,而不是Scala的继承和子类型化。 出于对Scala的有限了解,我在下面的Haskell中写了同样的东西。
Typeable
用于向下转换 -- Define traits
class Typeable a => Sql a
class (Typeable a, Sql a) => Statement a
class (Typeable a, Sql a) => Where a
-- Define case classes
data Union where Union :: (Statement a, Statement b) => a -> b -> Union deriving (Typeable)
data Select where Select :: Where a => a -> Select deriving (Typeable)
data And where And :: (Where a, Where b) => a -> b -> And deriving (Typeable)
data Or where Or :: (Where a, Where b) => a -> b -> Or deriving (Typeable)
data Equals where Equals :: Equals deriving (Typeable)
-- Define subtyping
instance Sql Union
instance Statement Union
instance Sql Select
instance Statement Select
instance Sql And
instance Where And
instance Sql Or
instance Where Or
instance Sql Equals
instance Where Equals
在Haskell中,您可能会使用求和类型而不是Statement
和Where
类。
class Sql a
instance Sql Statement
instance Sql Where
data Statement = Union Statement Statement | Select Where
data Where = And Where Where | Or Where Where | Equals
问题4的一种可能答案:
Haskell的类型推断(Hindley-Milner)在存在继承的情况下会遇到问题,因此Scala具有继承但功能较弱的类型推断器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.