2016-03-30 38 views
0

我想將現有的int庫擴展爲一個名爲「bigint」的新庫。我將數據類型bigint的類型保存爲int列表。基本上,我想要一個函數(讓它調用getbigint),它接受任何int並將其每個數字存儲在int列表的單獨單元中,然後返回此int列表。所以,如果我進入:如何在sml中定義新簽名

getbigint 9 

它應該給我:

val it =[9]:bigint 

我怎樣才能做到這一點?目前,我認爲這個函數的輸入只是單個數字的int。這是我迄今爲止所做的:

signature BigInt = 
    sig 
     type bigint = int list 
     val getbigint: int -> bigint 
    end; 

structure struct_bigint : BigInt = 
    struct 
     fun getbigint (i:int) = 
      let 
       val h = [i]:bigint 
      in h 
      end 
    end 
(*val j = getbigint 9;*) 

這是給錯誤。

回答

1

簽名不執行任何操作。它描述了外部世界的結構。把它看作一個規範。與之相匹配的結構必須提供簽名中元素的實現。請注意,當您運行代碼,您會收到以下錯誤:

Error: unmatched type specification: bigint 

SML檢測到你有沒有被通過結構的相應的實施相匹配的簽名什麼的。

一個最小的解決將僅僅是增加線路

type bigint = int list 

在結構定義的fun getbigint實施之前。這將允許行

val j = struct_bigint.getbigint 9; 

工作。但是 - 看起來有點愚蠢,有兩次 - 一次在簽名中,一次在結構中。而且,在某些方面,它愚蠢的。

實現細節並不真正屬於簽名。在簽名中具有type bigint以及在結構中根據int list執行將會更有意義。這將允許您稍後改變想法實現(例如,您想要使用數組而不是列表),以便使用該結構的代碼完全不受影響。喜歡的東西:

signature BIGINT = 
    sig 
     type bigint 
     val getbigint: int -> bigint 
    end 

structure BigInt : BIGINT = 
    struct 
     type bigint = int list 

     fun getbigint (i:int): bigint = [i];    
    end; 

我清理你的getbigint實施以來,let結合在它顯得有點毫無意義,並選擇一些更地道的簽名的名稱(全部大寫)和結構(駱駝與領先首都)。

最後,請注意,getbigint 9不會開箱即用。你可以做的三兩件事之一:

1)明確地使用合格的名稱:BigInt.getbigint 9

2)用線val getbigint = BigInt.getbigint給名稱getbigint其本意在當前範圍內

3)使用行open BigInt將結構的定義移動到頂層,之後getbigint 9將按預期工作。

當我開始在SML中編程時,我曾經打開很多結構(Char,List等)。如果你毫無意義地這樣做,遲早你會遇到一些錯誤,在這些錯誤中,打開一個結構會引起名稱衝突。出於這個原因,我現在幾乎總是使用方法1)或2)。