2

我是 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(前提是有区别的联合是其中之一,Door或者Window因为光穿透将是门与窗的不同公式)

4

1 回答 1

3

“继承”(又名“is-a”关系)的概念在技术上可以在 PureScript 中建模,但它既困难又尴尬。这有一个很好的理由:继承几乎从来都不是(我很想说“从不,时期”)对域建模的最方便、有效或可靠的方式。如今,即使是面向对象编程的辩护者也倾向于推荐聚合而不是继承。

需要注意的一件有用的事情是您实际上并不需要继承。您需要的是解决您领域中的某些特定问题,而继承只是您自然而然地寻求的解决方案,这可能是您过去的经验所决定的。

这使我们得出一个见解:对您正在建模的任何内容进行建模的特定方法将取决于实际问题是什么。很有可能,PureScript 有不同的建模机制。


但是,如果我的想法基于您在问题中给出的具体细节(即changeNameandcalculateTotalLightPenetration函数),我将通过聚合对其进行建模:“玻璃”将是周围的类型,并且作为其组成部分之一,特定类型的玻璃。这看起来像这样:

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
于 2022-01-31T03:04:23.807 回答