テストステ論

高テス協会会長が, テストステロンに関する情報をお届けします.

(msgpack-nim report) Haskellのnewtypeはdistinct

これがmsgpack-nimがNimオブジェクトをMsgオブジェクトに包むためのコンストラクタ.

    of mkBin32: vBin32*: seq[byte]
    of mkFixExt1:
      typeFixExt1*: uint8
      vFixExt1*: seq[byte]

そして使い勝手の都合上, 以下のようなファクトリを定義している. これはNimでヴァリアントを定義するための冗長なところ.

proc Bin32*(v: seq[byte]): Msg =
  assert(len(v) < (1 shl 32))
  Msg(kind: mkBin32, vBin32: v)

proc FixExt1*(t: uint8, data: seq[byte]): Msg =
  assert(len(data) == 1)
  Msg(kind: mkFixExt1, typeFixExt1: t, vFixExt1: data)

現在の定義の性能上の問題点は, いちいち包むコストがかかること. 関数呼び出しはinline出来るが, 包むコストはどうしようもない. こういう時のためにHaskellにはnewtypeがある. newtypeを使うとランタイムにはwrap/unwrapのコストがなくなる. これをNimで表現するのはdistinctである.

http://nim-lang.org/manual.html#distinct-type

というわけでやってみる. たぶん, FixExt1など, typeを持つものはtupleにする必要がある.

(追記)

と思ったら余裕で出来ない. Haskellでも, dataはnewtypeに出来ない. Haskellでもコンストラクタ複数持つものはnewtype不可であった. つまりこの目論見は死亡. 涙目だ. しかし, FixExt1をtupleで持つという案はのちのちのために良い気がする.