2013-06-24 2 views
2

Я попробовал следующее 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

Pro tip: включить «большую жирную ошибку» в отчет о проблеме. –

ответ

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

Это не объясняет, почему 'let m = map' работает и не принимает во внимание, что ограничение мономорфизма не применяется к переменным, которые имеют сигнатуру типа (которую ОП пыталась использовать, но он добавил подпись типа в неправильное место). – sepp2k

+0

Если бы я добавил подпись, отличную от полиморфного типа, в том же месте она все равно работала бы. – Jay