2009-08-29 47 views
10

我試圖通過學習Haskell來擴大我的想法。類型扣除在Haskell中如何工作?

我自找的功課是建立一個時鐘滴答發生器,它會給我泊松分佈的時間間隔,而最終的結果(經過長期鬥爭,我承認)是這樣的:

import System.Random 
poissonStream :: (Ord r, Random r, Floating r, RandomGen g) => r -> r -> r -> g -> [r] 
poissonStream rate start limit gen 
     | next > limit = [] 
     | otherwise  = next:(poissonStream rate next limit newGen) 
     where (rvalue, newGen) = random gen 
       next = start - log(rvalue)/rate 

但有兩件事(至少)我不明白:

爲什麼我需要「Ord r」以及「Floating r」? (我會期待某種自動繼承:「浮動」意味着「Ord」。)

通過什麼路徑隱含類型定義「rvalue :: Float」實現? 在GHCI我得到了我本來期望:

*Main System.Random> let (rvalue, newGen) = random (mkStdGen 100) 
<interactive>:1:23: 
    Ambiguous type variable `t' in the constraint: 
     `Random t' arising from a use of `random' at <interactive>:1:23-43 
    Probable fix: add a type signature that fixes these type variable(s) 

右值是一個鬆散的大炮,我有牽制:

*Main System.Random> let (rvalue, newGen) = random (mkStdGen 100) :: (Float, StdGen) 
*Main System.Random> rvalue 
0.18520793 

請溫柔與一個Haskell的n00b。

+2

恕我直言,如果這只是自我學習,我不會把它標記爲家庭作業。家庭作業問題意味着一個非常人爲的問題,並且通常會改變你得到的答案的類型(更多的是提示而不是你自己),除非你喜歡這個。 – cletus 2009-08-29 15:38:16

+0

@cletus:謝謝你的觀察。我認爲最好把它當做一個練習,而不是現實世界的問題。 – 2009-08-29 15:48:26

+2

我會把它標爲「愛好」或「自學」而不是「作業」。 「家庭作業」並不意味着「不是真實世界」,而是「不真正給我答案」。 – Chuck 2009-08-29 16:00:05

回答

12

爲什麼我需要「Ord r」以及「Floating r」? (我本來期望某種自動繼承:「浮動」意味着「奧德」)。

Floating應該是所有浮點數進行分類,包括複雜的。沒有複雜數字的排序。您可以使用RealFloat而不是Floating,這意味着Ord

通過什麼路徑隱含類型定義「rvalue :: Float」實現?

那麼你可以推斷,從使用rvalue的上下文中。它的參數log,並且

:t log 

log :: (Floating a) => a -> a 

所以rvalue必須在Floating類(所以這將是「某種類型的Floating類型類,不正是Float)。此外, log的結果與其輸入相同,用於startrate的計算,並與limit進行比較,它們都是r,因此rvalue將是r(這是合適的,因爲r也是Floating)。

在您的GHCi示例中,沒有更多上下文。鍵入

:t random (mkStdGen 100) 

這給你

random (mkStdGen 100) :: (Random a) => (a, StdGen) 

GHCI不知道填什麼類型在這裏a。它只知道它必須在類型Random

+1

當然可以。我並沒有想到Floating可能包含複雜的浮點數;並感謝您的RealFloat指針。 我*瞭解了GHCi中的行爲;我只是用它來比較我的功能顯然更自由的行爲。 非常感謝您給出明確的答案。 – 2009-08-29 17:46:11

2

在Haskell中,Ord和Floating是獨立的或者是orthogonal的概念。也許你認爲Floating只能引用非常特定的類型,比如Double和Float(這在大多數其他語言中就是這種情況)?

正如Rudiger指出的,有些類型是Float類的實例,它們不是Ord,因爲對於某些浮點類型(如Complex)沒有排序。複數除複數外的另一個例子是向量,爲此可以定義這些浮點函數,但不能使用任何明智的Ord-ering。

記住類型類只指定一組功能(如Java或C#的接口,如果這是考慮這個問題的一個有用的方法)必須爲一個類型一個定義; Ord,類型a只需要比較運算符,並且要成爲Floating的一個實例,一個類型a只需要實現Fractional並具有函數pi,exp,sqrt,log,sin,cos,..爲他們定義。這就是所有浮動的意思,沒有更多,沒有什麼。

+0

謝謝。是的,我讚賞正交的概念;我只是將它應用於一個太小的概念空間。 – 2009-08-29 19:06:59