首页 > 解决方案 > 避免明确的记录输入

问题描述

假设我有以下函数用于对理想化流进行操作:

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

这可以工作/编译,但不幸的是不得不在我的函数定义中乱扔我不关心的信息。row/col被忽略poke并且len. 但是,虽然通配符可以与 一起使用len,但不能与poke. 有没有办法重组这些函数,以便需要输入不太明确的类型,同时仍然能够进行模式匹配/解构?

标签: recordsmlsmlnj

解决方案


如果你给你的类型一个名字(比如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

推荐阅读