Was ist die Monomorphismusbeschränkung?
Ich bin verwirrt darüber, wie der Haskell-Compiler manchmal Typen ableitet, die weniger polymorph sind als erwartet, zum Beispiel bei der Verwendung von punktfreien Definitionen.
Es scheint, dass das Problem die "Monomorphismus-Einschränkung" ist, die in älteren Versionen des Compilers standardmäßig aktiviert ist.
Betrachten Sie das folgende Haskell-Programm:
{-# LANGUAGE MonomorphismRestriction #-}
import Data.List(sortBy)
plus = (+)
plus' x = (+ x)
sort = sortBy compare
main = do
print $ plus' 1.0 2.0
print $ plus 1.0 2.0
print $ sort [3, 1, 2]
Wenn ich das mit @ kompilieghc
Ich erhalte keine Fehler und die Ausgabe der ausführbaren Datei lautet:
3.0
3.0
[1,2,3]
Wenn ich das @ ändemain
body to:
main = do
print $ plus' 1.0 2.0
print $ plus (1 :: Int) 2
print $ sort [3, 1, 2]
Ich erhalte keine Fehler bei der Kompilierung und die Ausgabe lautet:
3.0
3
[1,2,3]
wie erwartet. Wenn ich jedoch versuche, es zu ändern:
main = do
print $ plus' 1.0 2.0
print $ plus (1 :: Int) 2
print $ plus 1.0 2.0
print $ sort [3, 1, 2]
Ich erhalte einen Tippfehler:
test.hs:13:16:
No instance for (Fractional Int) arising from the literal ‘1.0’
In the first argument of ‘plus’, namely ‘1.0’
In the second argument of ‘($)’, namely ‘plus 1.0 2.0’
In a stmt of a 'do' block: print $ plus 1.0 2.0
Das gleiche passiert beim Versuch, @ anzurufsort
zweimal mit verschiedenen Typen:
main = do
print $ plus' 1.0 2.0
print $ plus 1.0 2.0
print $ sort [3, 1, 2]
print $ sort "cba"
erzeugt den folgenden Fehler:
test.hs:14:17:
No instance for (Num Char) arising from the literal ‘3’
In the expression: 3
In the first argument of ‘sort’, namely ‘[3, 1, 2]’
In the second argument of ‘($)’, namely ‘sort [3, 1, 2]’
Warum tutghc
plötzlich denke, dassplus
ist nicht polymorph und benötigt einInt
Streit? Der einzige Verweis aufInt
ist ineine Bewerbun vonplus
, wie kann das wichtig sein, wenn die Definition eindeutig polymorph ist?Warum tutghc
plötzlich denke, dasssort
erfordert eineNum Char
instance?Mehr, wenn ich versuche, die Funktionsdefinitionen in ihrem eigenen Modul zu platzieren, wie in:
{-# LANGUAGE MonomorphismRestriction #-}
module TestMono where
import Data.List(sortBy)
plus = (+)
plus' x = (+ x)
sort = sortBy compare
Ich erhalte den folgenden Fehler beim Kompilieren:
TestMono.hs:10:15:
No instance for (Ord a0) arising from a use of ‘compare’
The type variable ‘a0’ is ambiguous
Relevant bindings include
sort :: [a0] -> [a0] (bound at TestMono.hs:10:1)
Note: there are several potential instances:
instance Integral a => Ord (GHC.Real.Ratio a)
-- Defined in ‘GHC.Real’
instance Ord () -- Defined in ‘GHC.Classes’
instance (Ord a, Ord b) => Ord (a, b) -- Defined in ‘GHC.Classes’
...plus 23 others
In the first argument of ‘sortBy’, namely ‘compare’
In the expression: sortBy compare
In an equation for ‘sort’: sort = sortBy compare
Warum ist nichtghc
n der Lage, den polymorphen Typ zu verwendOrd a => [a] -> [a]
zumsort
?nd warum machtghc
treatplus
undplus'
anders?plus
sollte den polymorphen Typ @ habNum a => a -> a -> a
und ich sehe nicht wirklich, wie sich das von der Art von @ unterscheidsort
und doch nursort raises an error.
<p>Last thing: if I comment the definition of <code>sort</code> the file compiles. However if I try to load it into <code>ghci</code> and check the types I get:</p><pre class="lang-none prettyprint-override"><code>*TestMono> :t plus
plus :: Integer -> Integer -> Integer
*TestMono> :t plus'
plus' :: Num a => a -> a -> a
</code></pre><p>Why isn't the type for <code>plus</code> polymorphic?</p>
This is the canonical question about monomorphism restriction in Haskell as discussed in <a href="https://meta.stackoverflow.com/questions/294053/can-we-provide-a-canonical-questionanswer-for-haskells-monomorphism-restrictio" rel="nofollow">the meta question</a>.