Haskell 支持类型类,例如相等:
class Eq a where
(==) :: a -> a -> Bool
Run Code Online (Sandbox Code Playgroud)
Rust 对类型特征做了同样的事情:
pub trait Draw {
fn draw(&self);
}
Run Code Online (Sandbox Code Playgroud)
现在,可以在 Haskell 中声明一个列表,其元素必须属于相等类型类:(Eq a => [a]
我相信在 Haskell 中a
称为约束类型)。但是,列表的元素仍然必须是同一类型!说,全部Integer
或全部Float
或某事。然而,在 Rust 中,人们可以拥有一个值列表(向量),其中每个值都实现给定的特征,但它们不一定是相同的具体类型:Vec<Box<dyn Draw>>
。有没有办法在 Haskell 中做同样的事情?就像,我想要一个值列表,但我关心的是每个值都属于某个类型类,但不一定是相同的具体类型。
在 Haskell 中,您可以使用存在类型来表达“此类型类的某些未知类型”。(在旧版本的 GHC 中,您将需要一些标准扩展。)
class Draw a where
-- whatever the methods are
data SomeDraw where
SD :: Draw a => a -> SomeDraw
type MyList = [SomeDraw]
Run Code Online (Sandbox Code Playgroud)
但是,请注意,这通常是矫枉过正,并导致已知的反模式。
例如,如果我们有一个类如下:
class Draw a where
draw :: a -> String
Run Code Online (Sandbox Code Playgroud)
那么上面的类型MyList
是同构的[String]
(或者至少在道德上是同构的)。与直接存储字符串相比,存储未知的“可绘制”对象(其唯一方法将其转换为字符串)没有任何优势。另请注意,Haskell 是惰性的,因此您可以“存储尚未评估的字符串”。
无论如何,类型类的存在量化也可以用通用的方式定义:
import Data.Kind
-- Ex has the same role of "dyn" in Rust here
data Ex (c :: Type -> Constraint) where
Ex :: c a => a -> Ex c
type MyList = [Ex Draw]
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
212 次 |
最近记录: |