不使用 class 表示受限类型
Representing a restricted type without using a class
在 F# 中,我可以在不定义 class 的情况下表示受限类型吗?
可以说我想表示第一个除以第二个的所有数字对。
在 C# 中我可以做到:
class PairDivides
{
int a {get;private set;}
int b {get;private set;}
PairDivides(int first, int second)
{
if (a % b != 0)
{
throw new Exception();
}
this.a = first;
this.b = second;
}
}
现在无法创建 PairDivides
实例,其中 b
不除 a
...
这能否在 F# 中仅使用函数构造(记录、可区分的联合、可能的活动模式等)来完成?
我希望能够创建和接收像这些对一样的东西,确保它们的构造正确。
您可以通过将类型设为私有来做到这一点。唯一的缺点是您需要提供函数来访问数据:
module Pairs =
type PairDivides = private { a: int; b: int }
let createPairDivides a b =
match a % b with
| 0 -> Some { PairDivides.a = a ; b = b }
| _ -> None
let print div =
printfn "{%d %d}" div.a div.b
let tryPrint div =
match div with
| Some a -> print a
| None -> printfn "None"
let a = Pairs.createPairDivides 2 2
let b = a.Value
// This is inaccessible: b.a
Pairs.createPairDivides 2 2 |> Pairs.tryPrint
Pairs.createPairDivides 2 3 |> Pairs.tryPrint
通过提供创建对的函数,以及根据需要使用或提取的函数,您可以完全消除创建无效对的能力(您将得到 None
而不是错误的对) 不使用异常。
缺点是您需要提供从对中提取值的机制,因为在当前模块外部使用时现在无法访问该类型。
也就是说,通过 classes 执行此操作也没有错。如果您愿意,可以通过创建 class 获得相同级别的执行:
type PairDivides private (a,b) =
member __.A = a
member __.B = b
static member Create a b =
match a % b with
| 0 -> Some(PairDivides(a,b))
| _ -> None
PairDivides.Create 2 2 |> printfn "%A"
PairDivides.Create 2 3 |> printfn "%A"
在 F# 中,我可以在不定义 class 的情况下表示受限类型吗? 可以说我想表示第一个除以第二个的所有数字对。
在 C# 中我可以做到:
class PairDivides
{
int a {get;private set;}
int b {get;private set;}
PairDivides(int first, int second)
{
if (a % b != 0)
{
throw new Exception();
}
this.a = first;
this.b = second;
}
}
现在无法创建 PairDivides
实例,其中 b
不除 a
...
这能否在 F# 中仅使用函数构造(记录、可区分的联合、可能的活动模式等)来完成?
我希望能够创建和接收像这些对一样的东西,确保它们的构造正确。
您可以通过将类型设为私有来做到这一点。唯一的缺点是您需要提供函数来访问数据:
module Pairs =
type PairDivides = private { a: int; b: int }
let createPairDivides a b =
match a % b with
| 0 -> Some { PairDivides.a = a ; b = b }
| _ -> None
let print div =
printfn "{%d %d}" div.a div.b
let tryPrint div =
match div with
| Some a -> print a
| None -> printfn "None"
let a = Pairs.createPairDivides 2 2
let b = a.Value
// This is inaccessible: b.a
Pairs.createPairDivides 2 2 |> Pairs.tryPrint
Pairs.createPairDivides 2 3 |> Pairs.tryPrint
通过提供创建对的函数,以及根据需要使用或提取的函数,您可以完全消除创建无效对的能力(您将得到 None
而不是错误的对) 不使用异常。
缺点是您需要提供从对中提取值的机制,因为在当前模块外部使用时现在无法访问该类型。
也就是说,通过 classes 执行此操作也没有错。如果您愿意,可以通过创建 class 获得相同级别的执行:
type PairDivides private (a,b) =
member __.A = a
member __.B = b
static member Create a b =
match a % b with
| 0 -> Some(PairDivides(a,b))
| _ -> None
PairDivides.Create 2 2 |> printfn "%A"
PairDivides.Create 2 3 |> printfn "%A"