2016-01-04 93 views
2

我正在學習多態和SML。我有點不確定如何處理元素的總和,同時保持函數多態。SML NJ - 多態自定義列表類型和總結元素

說,如果我有這樣的定義...

datatype 'a customList = nothing | customL of 'a * 'a customList 

這個列表...

val a = customL(2, customL(1, customL(3, nothing))) 

我想我需要使用(OP +),因爲多態處理,但我不能讓這些工作...

fun addElements (op +) nothing = 0 
| addElements (op +) (customL(x, nothing) = x 
| addElements (op +) (customL(x, xs)) = x + addElements xs 

我也認爲處理「沒有」可能會混淆類型,因爲我們二?

任何人都可以幫助得到這個工作?

更新

我想我更近一點,但我不明白爲什麼我得到一個錯誤......

exception EmptyList 

fun addElements (op +) nothing = raise EmptyList 
| addElements (op +) (customL(x, nothing)) = x 
| addElements (op +) (customL(x, xs)) = let val rest_of_list = addElements (op +) xs 
             in 
              (op +) (x, rest_of_list) 
             end 
+0

目前尚不清楚你在做什麼。 SML不支持運算符重載,並且「通用」不是在SML中使用得很多的詞(除了涉及簽名和函數的一些相當先進的領域)。 「多態」用於更多。你似乎想寫一種'fold'來爲你的自定義列表工作,你應該可以這樣做,但是'(op +)'是一個函數,可以被加入到你的函數中,而不是很難 - 接入定義。如果將它硬連接到定義中,那麼它只適用於「ints」或「reals」(但不是兩者)。 –

+0

對不起 - 我將泛型修正爲多態。我想要的是能夠總結列表的元素,但支持整數或實數。我知道,默認情況下,默認情況下,將類型視爲int,除非我傳入(op +)。硬連線是什麼意思?我希望列表能夠與customL(1,customL(2或customL(1.2,custom)(2.2 - 或者是一個整數列表或者一個實數列表)一起工作 – cpd1

+0

在SML中不可能寫一個函數'f' 'f(1,2)= 3'和'f(1.0,2.0)= 3.0' - 但你似乎想做一些可以寫這樣的函數 –

回答

2

你有什麼作品,但我不你不認爲它能做你認爲它的作用。例如,

addElements (op -) customL(2, customL(1, customL(3,nothing))) 

計算爲4,和

addElements (fn (x,y) => x) customL(2, customL(1, customL(3,nothing))) 

計算爲2

要看看發生了什麼,暫時忘掉customL。這個定義是不錯,但同構於list,所以看到的是與你的addElements是少分心把它寫在普通列表方面發生的事情:

fun addElements (op +) [] = raise Empty 
| addElements (op +) [x] = x 
| addElements (op +) (x::xs) = (op +)(x, addElements (op +) xs); 

這基本上是你有什麼,除了它使用模式匹配而不是let綁定。 SML接受此爲:

val addElements = fn : ('a * 'a -> 'a) -> 'a list -> 'a 

注意,類型有沒有什麼做加法或偶數(int或實際)。

發生了什麼事是你在重新定義(op +)在定義的正文。 SML大量使用預定義標識符而不是保留名稱。這種區別似乎迂腐,但它意味着你可以自由地重新定義任何事情:

val (op +) = 5; 
(op +) * 7; 

計算結果爲35

在定義(op +)的主體可以是'a * 'a -> 'a任何功能。因此 - 使用符號+和名稱addElements是有誤導性的。可以說最多的是它反映了你的意圖,但我不認爲這是重新定義內置操作符的充分理由,即使在本地範圍內。

一個不太誤導的方式來定義你的函數將沿的線條更:

fun combineElements combiner [] = raise Empty 
| combineElements combiner [x] = x 
| combineElements combiner (x::xs) = combiner (x,combineElements combiner xs); 

這裏名稱的選擇清楚地表明,它是採用了功能上的有序對相結合的多態函數列表到單個項目。

SML具有的標準功能foldl它做這一切,稍微:

- foldl (op +) 0 [1,2,3]; 
val it = 6 : int 
- foldl (op +) 0.0 [1.0, 2.0, 3.0]; 
val it = 6.0 : real 
- foldl (op +) 0 []; 
val it = 0 : int 

注意,它可以處理空列表。當我在評論中表示你似乎試圖做某種類型的fold時,我想到了這一點,但是你想在選擇加法作爲操作員時使用硬連線。

+0

謝謝!我以爲我可以換掉 - 是的。所以對於組合器,我會用combineElements +或combineElements(op +)替換它。我認爲這是後者。目前沒有電腦。我知道關於摺疊,但只是嘗試與列表不同的東西,並與總和 – cpd1

+0

@ cpd1卡住你是正確的,你需要(op +)語法與comnineElements –

+0

好的感謝您的幫助! – cpd1