我是 PureScript 新手。我正在 Purescript 中搜索密封类,以了解如何实现这一点,但我认为我还没有必要的 PS 术语。
PureScript 中拥有一堆扩展“基本”记录的记录的规范方法是什么,但随后有一个代表这些记录的“密封”集合的总和类型。
类似于 Kotlin 中的内容,
sealed class Glazing(val name: String, val area: Int) {
class Window(val name: String, val area: Int, val frameMaterial: String): BaseGlazing(name, area)
class Door(val name: String, val area: Int, val isPreHung: Boolean): BaseGlazing(name, area)
}
在 TypeScript 中,你可能会做类似的事情
interface BaseGlazing { ... }
interface Door extends BaseGlazing { ... }
interface Window extends BaseGlazing { ... }
type Glazing = Door | Window
and then you'd either take `A extends BaseGlazing` or `Glazing` (and use type guards) to do either of those two above functions.
本质上,我想要一个基类(技术上是抽象的),扩展它的东西,然后是扩展的总和类型/可区分联合,这样我就可以写,比如说,changeName::Glazing -> Glazing
(前提是具有 name
属性的基类),但也可以执行类似 calculateTotalLightPenetration::Array Glazing -> Number
的操作(前提是可区分联合)是门
或窗
之一,因为光穿透对于门和窗来说是不同的公式)
最佳答案
“继承”(又名“is-a”关系)的想法在技术上可以在 PureScript 中建模,但它既困难又尴尬。这是有充分理由的:继承几乎从来都不是(我很想说“从来没有,就这样”)最方便、最有效或最可靠的领域建模方式。如今,即使是 OOP 的辩护者也倾向于推荐聚合而不是继承。
需要观察的一件有用的事情是,您实际上并不需要继承。您需要是解决您领域中的某些特定问题,而继承只是您自然而然地寻求的解决方案,这可能是由您过去的经验决定的。
这使我们得出一个见解:对您正在建模的任何内容进行建模的特定方法将取决于实际问题是什么。 PureScript 有可能有不同的建模机制。
但是,如果我的想法基于您在问题中给出的具体细节(即 changeName
和 calculateTotalLightPenetration
函数),我会通过聚合对其进行建模:“玻璃窗” “将是周围的类型,并且作为其组成部分之一,它将具有特定类型的玻璃。这看起来像这样:
type Glazing = { name :: String, area :: Int, kind :: GlazingKind }
data GlazingKind = Window { frameMaterial :: String } | Door { isPreHung :: Boolean }
changeName :: Glazing -> Glazing
changeName g = g { name = "new name" }
calculateTotalLightPenetration :: Array Glazing -> Number
calculateTotalLightPenetration gs = sum $ individualPenetration <$> gs
where
individualPenetration g = case g.kind of
Door _ -> 0.3
Window _ -> 0.5
关于functional-programming - 表示所有扩展 "base"记录的记录总和类型概念的规范方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70920409/