PureScript - 什么是新类型?
PureScript - What is a newtype?
PureScript 手册定义了一个练习如下:
Define a Show instance for Point. Match the same output as the showPoint function from the previous chapter. Note: Point is now a newtype (instead of a type synonym), which allows us to customize how to show it. Otherwise, we'd be stuck with the default Show instance for records.
(https://book.purescript.org/chapter6.html)
但是,没有提供有关 newtype 是什么的信息。
什么是新类型?它是做什么用的?为什么它在这里可以工作,但不能打字?
Newtype 只是一种(或多种)类型的包装器。我们通常使用它来将预定义或已经可用的类型公开为新类型。
我们可以用 newtype 做很多有用的事情,其中之一是作者在你上面分享的章节中指定的。
当您指定
type Point =
{ x :: Number
, y :: Number
}
您实际上不能定义自己的类型 class 实例(例如显示实例),因为 Point
只是 Record 类型的类型同义词,它在 purescript 的 Prim 模块中预定义。
所以你用新类型包装它,并使它成为用户定义的类型。现在您可以派生任何您想要的实例。
您还可以使用它来创建更严格的值。例如,你想创建一个类型名称,当它的大小小于 6 时,你想强调一个错误。
所以你要做的是,
type Name = Either String String
然后你创建一个函数,
type Name = Either String String
createName' :: String -> Name
createName' name
| (length name) >= 6 = (Right name)
| otherwise = (Left "Invalid Name")
你现在很开心。但这并不限制其他开发人员做类似
的事情
myName :: Name
myName = (Right "a")
那么如何让 Name
仅由函数创建?
- 通过仅导入函数。
- 不导入
Name
问题是您不能执行第 2 步,因为 Name
只是一个类型同义词。
name :: Name
等同于 name :: Either String String
所以你用新类型
包装 Either String String
newtype StrictName = MkName (Either String String)
createName :: String -> StrictName
createName name
| (length name) >= 6 = MkName (Right name)
| otherwise = MkName (Left "Invalid Name")
现在你只导入函数和 StrictName(没有它的构造函数)
例如
module Data.MyTypes.Name
(StrictName,createName)
现在没有其他方法可以在不使用 createName 函数的情况下创建 StrictName 值。 (这也适用于 ADT 类型,但我更喜欢 newtype)
Newtype 还用于处理 orphan instances 和更多有用的东西。
Note : Newtype adds runtimes overhead as theres one more wrapper
around the original type.
PureScript 手册定义了一个练习如下:
Define a Show instance for Point. Match the same output as the showPoint function from the previous chapter. Note: Point is now a newtype (instead of a type synonym), which allows us to customize how to show it. Otherwise, we'd be stuck with the default Show instance for records. (https://book.purescript.org/chapter6.html)
但是,没有提供有关 newtype 是什么的信息。
什么是新类型?它是做什么用的?为什么它在这里可以工作,但不能打字?
Newtype 只是一种(或多种)类型的包装器。我们通常使用它来将预定义或已经可用的类型公开为新类型。
我们可以用 newtype 做很多有用的事情,其中之一是作者在你上面分享的章节中指定的。
当您指定
type Point =
{ x :: Number
, y :: Number
}
您实际上不能定义自己的类型 class 实例(例如显示实例),因为 Point
只是 Record 类型的类型同义词,它在 purescript 的 Prim 模块中预定义。
所以你用新类型包装它,并使它成为用户定义的类型。现在您可以派生任何您想要的实例。
您还可以使用它来创建更严格的值。例如,你想创建一个类型名称,当它的大小小于 6 时,你想强调一个错误。 所以你要做的是,
type Name = Either String String
然后你创建一个函数,
type Name = Either String String
createName' :: String -> Name
createName' name
| (length name) >= 6 = (Right name)
| otherwise = (Left "Invalid Name")
你现在很开心。但这并不限制其他开发人员做类似
的事情 myName :: Name
myName = (Right "a")
那么如何让 Name
仅由函数创建?
- 通过仅导入函数。
- 不导入
Name
问题是您不能执行第 2 步,因为 Name
只是一个类型同义词。
name :: Name
等同于 name :: Either String String
所以你用新类型
包装Either String String
newtype StrictName = MkName (Either String String)
createName :: String -> StrictName
createName name
| (length name) >= 6 = MkName (Right name)
| otherwise = MkName (Left "Invalid Name")
现在你只导入函数和 StrictName(没有它的构造函数) 例如
module Data.MyTypes.Name
(StrictName,createName)
现在没有其他方法可以在不使用 createName 函数的情况下创建 StrictName 值。 (这也适用于 ADT 类型,但我更喜欢 newtype)
Newtype 还用于处理 orphan instances 和更多有用的东西。
Note : Newtype adds runtimes overhead as theres one more wrapper around the original type.