簡體   English   中英

擴展OCaml中的現有類型

[英]Extending an existing type in OCaml

我最近一直在做一些OCaml編程來學習語言並且更熟悉函數式編程。 最近,我開始認為我希望能夠擴展現有類型(內置或我自己的類型),例如:

type bexp =
  And of bexp * bexp
| Or of bexp * bexp
| Xor of bexp * bexp
| Not of bexp;;

現在讓我們說我想在這種類型中添加一個Nop變體,但僅用於新類型 - 有點像繼承。 嘿,這些應該是代數數據類型,對吧? 那么為什么不是這樣的:

type nbexp = bexp | Nop nbexp ;;

...但這不是有效的OCaml,它給出了語法錯誤。 基本上,我想要做的就是說我希望nbexp包含bexp包含的所有內容,並為此添加一個Nop。 我想這是不可能的,因為,例如,如果您使用And構造函數,則無法確定它是bexp類型還是nbexp類型。 (我認為構造函數Nop采用nbexp也可能存在問題。)

那么有沒有辦法在OCaml中做這樣的事情? 而且,這是否是Haskell中可行的事情(也許是類型類)?

一個有趣的解決方案是使用多態變體:

type bexp =
[ `And of bexp * bexp
| `Or of bexp * bexp
| `Xor of bexp * bexp
| `Not of bexp ];;

type nbexp = [ bexp | `Nop of nbexp ];;

請注意,多態變體比普通變體更棘手,但允許擴展類型。

一個有趣的表達式評估示例,帶有擴展,使用多態變體可以在ocaml源的測試目錄中找到,請參閱svn

嘿,這些應該是代數數據類型,對吧?

對。 代數數據類型由標記(也稱為區分)的聯合和產品構成。 你想要的只是一個(非標記的)聯合,它不是代數數據類型,Haskell不支持。 OCaml具有多態變體(參見其他答案)。

Typed Scheme確實支持未標記的聯合,因此您可能需要檢查它。

正如你自己正確猜測的那樣,這在代數類型中是不可能的。 我同意Apocalisp的建議,你可以簡單地將nbexp的“繼承”部分nbexp在它自己的構造函數中。

我想補充一點,代數類型的遺傳缺乏是他們精彩的一部分。 這意味着諸如And(foo, bar)類的表達式被粗略地鍵入,並且轉換(向上或向下)在類型系統中沒有任何作用。 這樣可以提高安全性和清晰度。 它當然需要程序員明確處理他/她想要與bexp部分交互的nbexp ,但是如果你考慮它,那就是如何在實踐中實現更高的安全性和清晰度。

更新:Ocaml現在具有可擴展類型。 http://caml.inria.fr/pub/docs/manual-ocaml/extn.html#sec246

你會這樣做

type bexpr += Nop of bexpr

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM