避免显式记录类型
Avoiding explicit record typing
假设我有以下操作理想化流的函数:
fun Stream s = { pos = 0, row = 1, col = 0, str = s }
fun len { str, pos = _, row = _, col = _ } = String.size str
fun poke off { str, pos, row: int, col: int } =
let val n = pos + off in
if n >= 0 andalso n <= (String.size str) then SOME (String.sub(str, n)) else NONE
end
这 works/compiles,但不幸的是,我的函数定义中充满了我不关心的信息。 row
/col
被忽略 poke
和 len
。但是,虽然通配符可以与 len
一起使用,但不能与 poke
一起使用。有没有一种方法可以重构这些函数,以便不需要输入那么明确的输入,同时仍然能够模式 match/destructure?
如果你给你的类型起个名字(比如stream
),你可以更简单地引用它:
type stream = { pos : int, row : int, col : int, str : string }
fun Stream s = { pos = 0, row = 1, col = 0, str = s }
fun len ({ str, ... } : stream) = String.size str
fun poke off ({ str, pos, ... } : stream) =
let val n = pos + off in
if n >= 0 andalso n <= String.size str
then SOME (String.sub (str, n))
else NONE
end
或者,或多或少等同于:
datatype stream = STREAM of { pos : int, row : int, col : int, str : string }
fun Stream s = STREAM { pos = 0, row = 1, col = 0, str = s }
fun len (STREAM { str, ... }) = String.size str
fun poke off (STREAM { str, pos, ... }) =
let val n = pos + off in
if n >= 0 andalso n <= String.size str
then SOME (String.sub (str, n))
else NONE
end
假设我有以下操作理想化流的函数:
fun Stream s = { pos = 0, row = 1, col = 0, str = s }
fun len { str, pos = _, row = _, col = _ } = String.size str
fun poke off { str, pos, row: int, col: int } =
let val n = pos + off in
if n >= 0 andalso n <= (String.size str) then SOME (String.sub(str, n)) else NONE
end
这 works/compiles,但不幸的是,我的函数定义中充满了我不关心的信息。 row
/col
被忽略 poke
和 len
。但是,虽然通配符可以与 len
一起使用,但不能与 poke
一起使用。有没有一种方法可以重构这些函数,以便不需要输入那么明确的输入,同时仍然能够模式 match/destructure?
如果你给你的类型起个名字(比如stream
),你可以更简单地引用它:
type stream = { pos : int, row : int, col : int, str : string }
fun Stream s = { pos = 0, row = 1, col = 0, str = s }
fun len ({ str, ... } : stream) = String.size str
fun poke off ({ str, pos, ... } : stream) =
let val n = pos + off in
if n >= 0 andalso n <= String.size str
then SOME (String.sub (str, n))
else NONE
end
或者,或多或少等同于:
datatype stream = STREAM of { pos : int, row : int, col : int, str : string }
fun Stream s = STREAM { pos = 0, row = 1, col = 0, str = s }
fun len (STREAM { str, ... }) = String.size str
fun poke off (STREAM { str, pos, ... }) =
let val n = pos + off in
if n >= 0 andalso n <= String.size str
then SOME (String.sub (str, n))
else NONE
end