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
任何类型,并允许二叉树中的任何类型.
这给出了"这些类型可以互换吗?"的三个答案.
没有4:编译器取代程序员,因为他们碰巧使用了几个Ints和一个像其他函数一样的String.
*我说Haskell不太可能改为结构类型.有一些讨论要介绍某种形式的可扩展记录,但没有计划将(Int,(Int,Int))
计数视为相同(Int, Int, Int)
或Triple {one::Int, two::Int, three::Int}
相同Triple2 {one2::Int, two2::Int, three2::Int}
.
Haskell记录实际上并不比其他类型系统"结构化".每种类型都是完全指定的,或"特别模糊"(即使用类型类定义).
要同时允许HRec
和HRec2
使用f
,您有两个选择:
代数类型:
在这里,您定义HRec
和HRec2
记录两者都是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
(或任意函数)来获取我们所需的数据!