2014-10-17 60 views
0

您可以使用記錄中的兩個字段來定義第三個字段嗎?例如使用記錄中的兩個字段來定義記錄中的第三個字段

type t = { a : int; b : int; c : int } 
{ a = 1 ; b = 2; c = a * b}; 

甚至更​​好

type t = { a : int; b : int; c = a * b } 

或者其他類似的是,在ocaml的影響?我知道你可以很容易地編寫一個函數來計算c,而不是將它存儲在一個字段中。

回答

3

您提出的兩種語法都不適用於OCaml,就像我們今天所使用的。

您可以編寫一個函數來構建一個記錄:

# let mkt a b = { a; b; c = a * b };; 
val mkt : int -> int -> t = <fun> 
# mkt 2 3;; 
- : t = {a = 2; b = 3; c = 6} 

你可以使用一個對象類型,使c是按需計算:

# class c a b = object method a = a method b = b method c = a * b end;; 
class c : 
  int -> int -> object method a : int method b : int method c : int end 
# let x = new c 3 4;; 
val x : c = <obj> 
# (x#a, x#b, x#c);; 
- : int * int * int = (3, 4, 12) 

這是最好的,我可以想出用。

3

如果您想確保每個t都是爲某個字段創建的,那麼您可以使用該模塊系統。 private類型將允許其他人訪問該字段,但不允許t的直接創建(或突變,它有可變部分)。

它看起來像這樣:

module Foo : sig 
    type t = private { a : int; b : int; c : int } 
    val create : int -> int -> t 
end = struct 
    type t = { a : int; b : int; c : int } 
    let create a b = { a; b; c = a * b; } 
end 

這是強制執行不變一種非常有效的方式,但它可能是一個有點沉重。

1

存在1種無效的方式。

讓我們看一下Haskell代碼:

data Rec = Rec {a::Int, b::Int, c::Int} 

d = Rec {a = 2, b = 3, c = a d * b d} 

> d 
Rec {a = 2, b = 3, c = 6} 

因此,模擬同OCaml中,我們必須改變一個位類型:

type t = { a : int; b : int; c : int lazy_t} 

> let rec d = {a = 2; b = 3; c = lazy (d.a * d.b)};; 
val d : t = {a = 2; b = 3; c = <lazy>} 

> Lazy.force d.c;; 
- : int = 6 

> d 
- : t = {a = 2; b = 3; c = lazy 6}