为什么Haskell没有结构类型的记录?

use*_*220 9 haskell record structural-typing

我听说Haskell被描述为具有结构类型.据我了解,记录是一个例外.例如foo,HRec2即使在某些类型的东西中也不能调用它们,HRec并且HRec2在它们的字段中只是名义上不同.

data HRec = HRec { x :: Int, y :: Bool }
data HRec2 = HRec2 { p :: Int, q :: Bool }

foo :: HRec -> Bool
Run Code Online (Sandbox Code Playgroud)

是否有一些解释拒绝将结构类型扩展到包括记录在内的所有内容?

是否存在结构类型的静态类型语言,即使是记录?对于所有静态类型语言,我可以阅读一下这个问题吗?

not*_*job 12

Haskell有结构化类型,但不是结构类型,而且不太可能改变.*

拒绝允许名义上不同但结构相似的类型作为可互换的参数被称为类型安全.那是一件好事.Haskell甚至有一个newtype声明来提供名义上不同的类型,以允许您强制执行更多的类型安全.类型安全是一种很容易早期捕获错误的方法,而不是在运行时允许它们.

除了amindfv的好答案,包括通过类型类的特殊多态(有效地是程序员声明的特征等价),还有参数多态,你允许绝对任何类型,所以[a]允许列表中的BTree a任何类型,并允许二叉树中的任何类型.

这给出了"这些类型可以互换吗?"的三个答案.

  1. 没有; 程序员没有这么说.
  2. 由于程序员这么说,因此具体用于特定目的.
  3. 不关心 - 我可以对这个数据集做同样的事情,因为它不使用数据本身的任何属性.

没有4:编译器取代程序员,因为他们碰巧使用了几个Ints和一个像其他函数一样的String.

*我说Haskell不太可能改为结构类型.有一些讨论要介绍某种形式的可扩展记录,但没有计划将(Int,(Int,Int))计数视为相同(Int, Int, Int)Triple {one::Int, two::Int, three::Int}相同Triple2 {one2::Int, two2::Int, three2::Int}.

  • 当你连续写了三篇冗长的评论时,是时候承认你可能会回答.转换为答案. (3认同)

ami*_*dfv 9

Haskell记录实际上并不比其他类型系统"结构化".每种类型都是完全指定的,或"特别模糊"(即使用类型类定义).

要同时允许HRecHRec2使用f,您有两个选择:

代数类型:

在这里,您定义HRecHRec2记录两者都是HRec类型的一部分:

data HRec = HRec  { x :: Int, y :: Bool }
          | HRec2 { p :: Int, q :: Bool }

foo :: HRec -> Bool
Run Code Online (Sandbox Code Playgroud)

(或者,也许更惯用:)

data HRecType = Type1 | Type2
data HRec = HRec { hRecType :: HRecType, x :: Int, y :: Bool }
Run Code Online (Sandbox Code Playgroud)

类型类

在这里,您可以定义foo为能够接受任何类型作为输入,只要为该类型编写了类型类实例:

data HRec  = HRec  { x :: Int, y :: Bool }
data HRec2 = HRec2 { p :: Int, q :: Bool }

class Flexible a where
   foo :: a -> Bool

instance Flexible HRec where
   foo (HRec a _) = a == 5 -- or whatever

instance Flexible HRec2 where
   foo (HRec2 a _) = a == 5
Run Code Online (Sandbox Code Playgroud)

使用类型类可以让你比常规的结构类型更进一步 - 你可以接受嵌入了必要信息的类型,即使类型表面上看起来不相似,例如:

data Foo = Foo { a :: String, b :: Float }
data Bar = Bar { c :: String, d :: Integer }

class Thing a where
   doAThing :: a -> Bool

instance Thing Foo where
    doAThing (Foo x y) = (x == "hi") && (y == 0)

instance Thing Bar where
    doAThing (Bar x y) = (x == "hi") && ((fromInteger y) == 0)
Run Code Online (Sandbox Code Playgroud)

我们可以运行fromInteger(或任意函数)来获取我们所需的数据!

  • @luqui - 要回答这个问题,我想你需要说的是"haskell并没有真正的结构打字." 我添加了解决方案,以显示OP在haskell中获得相同效果的惯用方法 (2认同)