2014-01-17 40 views
-1

在艾菲爾一個被允許使用一個expanded class不從堆中分配。從開發人員的角度來看,很少需要考慮從Int到Float的轉換,因爲它是自動的。我的問題是這樣的:爲什麼Haskell不會選擇類似的方法來建模Num。具體來說,讓我們考慮一下Int實例。這裏是我的問題的理由:原始類型作爲Haskell中的擴展類?

 [1..3] = [1,2,3] 
     [1..3.5] = [1.0,2.0,3.0,4.0] -- rounds up 

第二個名單是我沒想到,因爲有被定義的任何兩個整數之間進行無限次的浮點數的東西。當然,一旦我們測試了序列,很明顯它會返回浮點數的上限。這些轉換所需的原因之一是讓我們計算一組整數的平均值。

在艾菲爾數量類型層次是一個比較程序員友好和轉換髮生在需要:例如創建序列仍然可以是一組整數的導致一個浮點的意思。這具有可讀性優勢。

是否有擴展的類沒有在Haskell實現的原因是什麼?任何引用將極大地幫助。

@ony:我們不會使用原語時所面臨的同樣的問題:關於並行的戰略意義呢?手工做discourage使用原語和對我來說很有意義,一般在以往任何時候,我們可以用我們的原語可能需要使用抽象類。在嘗試使用數字的平均值時,我遇到的問題是缺少Fractional Int實例,並且爲什麼5/3不提升爲浮點數,而不必創建浮點數組來實現相同的結果。關於Int和Integer的分數實例爲什麼沒有定義,肯定有一個原因嗎?這可以幫助我更好地理解基本原理。

@leftroundabout:這個問題不是關於擴展類本身,而是這樣一個功能可以提供的便利,儘管單獨這個功能不足以處理類型提升以從int中浮動,例如我的響應中提到的@ony。讓我們平均的經典例子並試圖將其定義爲

> [Int] :: Double 
    let mean xs = sum xs/length xs (--not valid haskell code) 
    [Int] :: Double 
    let mean = sum xs/fromIntegral (length xs) 

我也喜歡它,如果我沒有打電話給fromIntegral得到均值函數的工作和聯繫的缺失Fractional Int。雖然解釋似乎有意義,但它必須,我不明白的是,如果我很清楚我期望有一個雙重字符,並且在我的類型簽名中聲明它不足以執行適當的轉換嗎?

+5

這真的是一個關於擴展類的問題嗎?我對此表示懷疑。你能把它與一些更廣泛的編程語言聯繫起來嗎? C當然也會自動進行類型轉換(雖然非常不安全)。我不認爲你已經很好地掌握了Haskell的類型類是如何工作的 - 在你的例子中,什麼都沒有。嘗試列表[0.5 .. 4]'。 – leftaroundabout

+2

後一個序列以4.0結尾的事實是浮點數的'enumFromTo' Haskell定義中的一個錯誤。它曾經是正確的,但卻被誤導爲使其更加「用戶友好」。 – augustss

+1

@augustss正在點是相關的,但[本是否爲「錯誤」是有爭議的(http://stackoverflow.com/questions/7290438/haskell-ranges-and-floats/7296160#7296160)。 – leftaroundabout

回答

1

至於行爲@ J.Abrahamson已經回覆。這是定義enumFromThenTo

至於設計... 其實GHC有Float#,它表示unboxed類型(可以在任何地方分配,但值是嚴格的)。 由於Haskell是一種懶惰的語言,它假定大多數值最初不需要,直到它們實際引用具有嚴格參數的原語爲止。 考慮length [2..10]。在這種情況下,如果沒有優化,Haskell甚至可能會避免生成數字並簡單地建立一個列表(沒有值)。可能更有用的例子是takeWhile (<100) [x*(x-1) | x <- [2..]]

但你不應該認爲我們的開銷在這裏,因爲你是在抽象了大拇指所有的東西,寫的語言(除了嚴格的記號)。 Haskell編譯器必須將其作爲自己的工作。即當編譯器能夠告訴列表的所有元素將被引用(轉換爲正常形式)並且它決定在一個返回堆棧內處理它時,它可以將其分配到堆棧上。

此外,使用這種方法,您可以通過使用多個CPU內核獲得更多代碼。想象一下,使用Strategies您的列表正在不同的內核上處理,因此他們應該共享堆上的公共數據(而不是堆棧)。

3

[a..b]enumFromTo a b的簡寫,這是Enum類型類別的一種方法。它開始於asucc s的超過第一時間b至。

[a,b..c]是簡寫enumFromThenTo a b c類似於enumFromTo除了代替succ荷蘭國際集團它增加了每個時間差b-a。默認情況下,此差異是通過往返Int來計算的,因此可能會或可能不會遵守分數差異。這就是說,Double作品如你所期望

Prelude> [0.0, 0.5.. 10] 
[0.0,0.5,1.0,1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5,7.0,7.5,8.0,8.5,9.0,9.5,10.0] 

[a..]enumFrom a剛剛succ永遠的簡寫。

[a,b..]enumFromThen a b的簡寫,它只是永遠添加(b-a)