OCamlテクニック/ghost
OCamlで幽霊型を応用してみました。
お金型に税込みかどうかの区別を付けて、二重に税金を計算することを
防ぐことができます。
まずシグネチャーを定義します。
ここでは、裸の金額と税込みの金額を区別した型を定義して、
tax関数は裸の金額にしか適用できないよう制限します。
# module type MoneySig = sig
type 'a money constraint 'a = [< `Naked | `Taxed ]
val make : float -> [`Naked] money
val add : 'a money -> 'a money -> 'a money
val mul : 'a money -> 'a money -> 'a money
val tax : [`Naked] money -> [`Taxed] money
val show : 'a money -> string
end
;;
module type MoneySig =
sig
type 'a money constraint 'a = [< `Naked | `Taxed ]
val make : float -> [ `Naked ] money
val add : ([< `Naked | `Taxed ] as 'a) money -> 'a money -> 'a money
val mul : ([< `Naked | `Taxed ] as 'a) money -> 'a money -> 'a money
val tax : [ `Naked ] money -> [ `Taxed ] money
val show : [< `Naked | `Taxed ] money -> string
end
先ほどのシグネチャーを適用したモジュールを作ります。
実体をfloatとしています。
# module Money : MoneySig = struct
type 'a money = float constraint 'a = [< `Naked | `Taxed ]
let make x = x
let add = (+.)
let mul = ( *.)
let tax x = x *. 1.05
let show = string_of_float
end;;
module Money : MoneySig
では、Moneyモジュールを使ってみましょう。
# let juice = Money.make 120.0;;
val juice : [ `Naked ] Money.money = <abstr>
ジュースは120円、税抜きとします
# Money.tax (Money.tax juice);;
This expression has type [ `Taxed ] Money.money but is here used with type
[ `Naked ] Money.money
These two variant types have no intersection
二重に課税すると型エラーです。
# Money.add juice juice;;
- : [ `Naked ] Money.money = <abstr>
# let pay = Money.tax juice;;
val pay : [ `Taxed ] Money.money = <abstr>
# print_string (Money.show pay);;
126.- : unit = ()
通常の使い方はこんな感じ。
# Money.add juice pay;;
Characters 16-19:
Money.add juice pay;;
^^^
This expression has type [ `Taxed ] Money.money but is here used with type
[ `Naked ] Money.money
These two variant types have no intersection
#
裸の金額と税込み金額をごちゃ混ぜにして足し算しようとしても、きちんとエラーになります
- すごいなるほど!ところでconstraintというのは予約語ですか?こういう型の構文をはじめて見るのですが -- けいご?
- ああ,'aが[`Naked]か[`Taxed]の場合しかないという意味ですね?. -- けいご?
- constraint は予約語です。意味はそのまんまですね 今回は多相ヴァリアントを閉じた形でconstraintにしています。 -- ogasawara?
- GtNuuJzZF -- luwuwv?
- , http://www.syracuse.com/forums/profile.ssf?nickname=n5CpCPqK ambien, xzf, http://www.syracuse.com/forums/profile.ssf?nickname=352Ov5jH diflucan, :-[[[, http://www.pennlive.com/forums/profile.ssf?nickname=dZ3l5jrx tramadol, 588, http://www.oregonlive.com/forums/profile.ssf?nickname=xzIEQnqc zoloft, ndre, http://www.silive.com/forums/profile.ssf?nickname=wJtcq63c actos, 54679, http://www.silive.com/forums/profile.ssf?nickname=soXPpVeZ ventolin, 59287, http://www.pennlive.com/forums/profile.ssf?nickname=ajOOVrbb allegra, 841, http://www.masslive.com/forums/profile.ssf?nickname=tBL6Kn60 celebrex, zsoijr, http://www.oregonlive.com/forums/profile.ssf?nickname=7likbuhv seroquel, 621, http://www.pennlive.com/forums/profile.ssf?nickname=9HV7TuHa plavix, 5205, http://www.masslive.com/forums/profile.ssf?nickname=fY8Neqtw vytorin, 142321, http://www.oregonlive.com/forums/profile.ssf?nickname=pvDctzlh codeine, 7893, http://www.nj.com/forums/profile.ssf?nickname=dNb4YjcI percocet, zxzvyr, http://www.syracuse.com/forums/profile.ssf?nickname=Ql09AvBD clomid, %-[[, http://www.oregonlive.com/forums/profile.ssf?nickname=SlMYjyZK prozac, :-), http://www.mlive.com/forums/profile.ssf?nickname=xXUJAGcZ nexium, =-[[[, http://www.cleveland.com/forums/profile.ssf?nickname=QCgYczZ1 actos, 8-OOO, http://www.syracuse.com/forums/profile.ssf?nickname=VBw2PwXg tenuate, 239112, http://www.oregonlive.com/forums/profile.ssf?nickname=paYyhkkb proscar, esr, http://www.mlive.com/forums/profile.ssf?nickname=O8t5r7jC phentermine, aid, http://www.mlive.com/forums/profile.ssf?nickname=V1n8IRdn aciphex, xenlu, http://www.silive.com/forums/profile.ssf?nickname=9v8TzeNT femara, 134, http://www.masslive.com/forums/profile.ssf?nickname=pDQqupAD lexapro, %[, http://www.syracuse.com/forums/profile.ssf?nickname=nNicgS92 kamagra, hzp, -- synthroid?