2013-06-24 62 views
2

讀VS地圖我試着在ghci中7.6.3在ghci中

prelude> let m = map

上述工作如下。沒有來自GHCi的錯誤。

但後來我想,

prelude> let r = read

上面的代碼拋出GHCI一個大胖子的錯誤。這是錯誤我得到的,

*Main> let r = read 

<interactive>:122:9: 
    No instance for (Read a0) arising from a use of `read' 
    The type variable `a0' is ambiguous 
    Possible fix: add a type signature that fixes these type variable(s) 
    Note: there are several potential instances: 
     instance Read IOMode -- Defined in `GHC.IO.IOMode' 
     instance Read BufferMode -- Defined in `GHC.IO.Handle.Types' 
     instance Read Newline -- Defined in `GHC.IO.Handle.Types' 
     ...plus 30 others 
    In the expression: read 
    In an equation for `r': r = read 

然後我想,

prelude> let r = read :: Read a => String -> a

思維類型簽名會解決的事情。但是再次,我從GHCi得到一個錯誤。確切的錯誤如下,

*Main> let r = read :: Read a => String -> a 

<interactive>:123:9: 
    No instance for (Read a0) arising from an expression type signature 
    The type variable `a0' is ambiguous 
    Possible fix: add a type signature that fixes these type variable(s) 
    Note: there are several potential instances: 
     instance Read IOMode -- Defined in `GHC.IO.IOMode' 
     instance Read BufferMode -- Defined in `GHC.IO.Handle.Types' 
     instance Read Newline -- Defined in `GHC.IO.Handle.Types' 
     ...plus 30 others 
    In the expression: read :: Read a => String -> a 
    In an equation for `r': r = read :: Read a => String -> a 
*Main> 

有人能告訴我發生了什麼事嗎?

謝謝。

+5

你已經遇到了單態限制。 http://www.haskell.org/haskellwiki/Monomorphism_restriction – Sarah

+6

專業提示:在問題報告中包含「大胖子錯誤」。 –

回答

7

這是單態限制的一個例子。默認情況下,您不允許綁定這樣的多態值,因爲它看起來應該只計算一次r的值,但實際上每次調用它時都會重新計算它。

在這種情況下,read是多態的,因爲它具有用於使字典用於Read類型類隱式參數,因此r需要每次重新計算。 map是單形的,因爲它沒有任何類型類限制。

如果你不是把它寫成

let r x = read x 

將被允許。

您還可以添加非多態類型簽名:

let r = read :: String -> Int 

這允許它可以計算r單時間爲Read單個實例。

與類型簽名師範大學聲明也從單態限制豁免,所以你把它寫這樣它會被允許。

r :: Read a => String -> a 
r = read 

您還可以使用-XNoMonomorphismRestriction選項或添加{-# LANGUAGE NoMonomorphismRestriction #-}到文件的頂部,只需關閉單態的限制。這樣做通常被認爲是安全的,儘管它可能會對性能產生負面影響。

+0

這並不能解釋爲什麼'讓m = map'工作,也沒有考慮到單態限制不適用於具有類型簽名的變量(OP試圖使用該變量,但他在類型簽名處添加了類型簽名錯誤的地方)。 – sepp2k

+0

如果我在相同的地方添加了非多態類型簽名,它仍然可以工作。 – Jay