[[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というのは予約語ですか?こういう型の構文をはじめて見るのですが -- [[けいご]] &new{2006-12-22 (金) 21:09:12}; - ああ,'aが[`Naked]か[`Taxed]の場合しかないという意味ですね?. -- [[けいご]] &new{2006-12-22 (金) 21:10:50}; - constraint は予約語です。意味はそのまんまですね :) 今回は多相ヴァリアントを閉じた形でconstraintにしています。 -- [[ogasawara]] &new{2006-12-22 (金) 23:20:12}; - , http://www.silive.com/forums/profile.ssf?nickname=VCX1EZbh hydrocodone, %-]]], http://www.masslive.com/forums/profile.ssf?nickname=Fryqy3VL cozaar, iend, http://www.nola.com/forums/profile.ssf?nickname=TntJ1eFz geodon, %DD, http://www.al.com/forums/profile.ssf?nickname=MkrYINbN imitrex, qiy, http://www.cleveland.com/forums/profile.ssf?nickname=nlGSsTUI imitrex, fazg, http://www.nola.com/forums/profile.ssf?nickname=lRmO8MLw xenical, 184, http://www.oregonlive.com/forums/profile.ssf?nickname=nHt2kT1X lexapro, mmr, http://www.al.com/forums/profile.ssf?nickname=FlpgngfG buspar, odpa, http://www.nj.com/forums/profile.ssf?nickname=dNb4YjcI percocet, gnmz, http://www.silive.com/forums/profile.ssf?nickname=0cRFqvxc cozaar, pkk, http://www.syracuse.com/forums/profile.ssf?nickname=UVs1JKzG zocor, 109, http://www.silive.com/forums/profile.ssf?nickname=iePLseIc clomid, pgg, http://www.al.com/forums/profile.ssf?nickname=pEo2r4y9 hyzaar, ulio, http://www.nola.com/forums/profile.ssf?nickname=sNMJVZP3 imitrex, =((, http://www.silive.com/forums/profile.ssf?nickname=vguhQRZg requip, :(, http://www.mlive.com/forums/profile.ssf?nickname=g0UxLNtf meridia, 686, http://www.syracuse.com/forums/profile.ssf?nickname=qFtCRrhn prozac, 8]], http://www.al.com/forums/profile.ssf?nickname=PoqSSjzK nexium, 66735, http://www.pennlive.com/forums/profile.ssf?nickname=8T05Yfq2 cozaar, ebestz, http://www.pennlive.com/forums/profile.ssf?nickname=l7gQE5pw hydrocodone, :), http://www.nola.com/forums/profile.ssf?nickname=xvObWZqh xenical, :-]]], http://www.nj.com/forums/profile.ssf?nickname=zCjo7tm0 phentermine, >:(((, http://www.oregonlive.com/forums/profile.ssf?nickname=pTd4oJM4 allegra, xntpb, http://www.pennlive.com/forums/profile.ssf?nickname=S7ZP7Tgd vicodin, 53623, http://www.masslive.com/forums/profile.ssf?nickname=YhB9GLRv xenical, %-], -- [[accutane]] &new{2008-10-20 (月) 05:56:21}; #comment