2014-02-25 35 views
8

我嘗試了幾個項目目前轉換爲classy-prelude。雖然大多數行爲似乎對我來說很簡單,但(head . head)在簡單的2D列表上給出了神祕的錯誤。優雅-序曲(頭。頭)

考慮以下GHCI會議:

Prelude> (head . head) [[1,2],[3,4]] 
1 

讓我們試試這個與ghci -XNoImplicitPreludeclassy-prelude

> import ClassyPrelude 
ClassyPrelude> (head . head) [[1,2],[3,4]] 

<interactive>:10:1: 
    Couldn't match type `MinLen (Succ nat1) mono1' with `[[t0]]' 
    Expected type: [[t0]] -> Element mono0 
     Actual type: MinLen (Succ nat1) mono1 -> Element mono0 
    The function `head . head' is applied to one argument, 
    but its type `MinLen (Succ nat1) mono1 -> Element mono0' 
    has only one 
    In the expression: (head . head) [[1, 2], [3, 4]] 
    In an equation for `it': it = (head . head) [[1, 2], [3, 4]] 

我認爲GHC根本無法正確解析類型多維名單。有沒有什麼辦法可以幫助它,而不訴諸於(Prelude.head . Prelude.head)

+1

'MinLen(Succ nat1)mono1' =>我認爲你需要一個非空列表類型 –

+0

@MauricioScheffer你到底在哪裏我想要一個非空列表? '[[1,2],[3,4]]'是在兩個維度是非空的,並且GHC * *應該能夠從它派生一個Int類型(它可以爲'Prelude.head'做) –

+4

@UliKöhler我認爲MauricioScheffer是對的。這些列表非空,但它們的*類型*不是「非空列表」類型。 –

回答

10

正如在評論中已經提到的那樣,優雅的序言head函數僅適用於保證類型系統至少有一個元素的遍歷器,因此它不必是局部的。因爲所有的名單都以最低的一個元素,你可以只使用非空列表類型:

head . head $ mlcons (mlcons 1 $ mlcons 2 $ toMinLenZero []) $ mlcons (mlcons 3 $ mlcons 4 $ toMinLenZero []) $ toMinLenZero [] :: Int 
-- 1 

(從ml功能都來自MinLen模塊的mono-traversable,這是由classy-prelude轉口)

如果你只想Prelude.head功能的行爲,可以再次從mono-traversable包中使用unsafeHead,默認情況下出口:

unsafeHead . unsafeHead [[1,2],[3,4]] 
-- 1 

還有該模塊,可如果你喜歡處理失敗不同,不出事的整個程序中使用的headMay

+2

好的答案,我也只是在'headEx'中。該和之間的差'unsafeHead'是'unsafeHead'可能會引起與特定數據類型('VECTOR'並且特別'ByteString')段錯誤,而'headEx'是保證引發空容器上的異常。 –