Ich begann 99 Haskell Probleme zu tun und ich war auf problem 7 und meine Unittests explodierten.Monomorphie-Beschränkung für mich bitte erklären?
Offenbar ist es aufgrund dieser: http://www.haskell.org/haskellwiki/Monomorphism_restriction
Ich wollte nur sicherstellen, dass ich das richtig verstanden, weil ich ein bisschen verwirrt bin.
situation 1: func a
wird ohne typ def oder mit einem nicht strikten typ def definiert und dann einmal verwendet, der compiler hat keine probleme, die den typ zur kompilierungszeit ableiten.
situation 2: das gleiche func a
wird oft im Programm verwendet, der Compiler kann nicht zu 100% sicher sein, was der Typ ist, wenn er die Funktion für die gegebenen Argumente nicht neu berechnet.
Um den Berechnungsverlust zu vermeiden, beschwert sich ghc dem Programmierer, dass es einen strikten Typ def auf a
benötigt, um richtig zu arbeiten.
ich in meiner Situation denken, assertEqual
hat den Typ def von
assertEqual :: (Eq a, Show a) => String -> a -> a -> Assertion
Ich erhalte eine Fehlermeldung, wenn test3
definiert wurde, dass ich mit den Worten interpretiert, dass es für die Rückkehr von testcase3
2 möglichen Typen hatte (Zeige und Eq) und wusste nicht weiter.
Klingt das richtig oder bin ich komplett ausgeschaltet?
problem7.hs:
-- # Problem 7
-- Flatten a nested list structure.
import Test.HUnit
-- Solution
data NestedList a = Elem a | List [NestedList a]
flatten :: NestedList a -> [a]
flatten (Elem x) = [x]
flatten (List x) = concatMap flatten x
-- Tests
testcase1 = flatten (Elem 5)
assertion1 = [5]
testcase2 = flatten (List [Elem 1, List [Elem 2, List [Elem 3, Elem 4], Elem 5]])
assertion2 = [1,2,3,4,5]
-- This explodes
-- testcase3 = flatten (List [])
-- so does this:
-- testcase3' = flatten (List []) :: Eq a => [a]
-- this does not
testcase3'' = flatten (List []) :: Num a => [a]
-- type def based off `:t assertEqual`
assertEmptyList :: (Eq a, Show a) => String -> [a] -> Assertion
assertEmptyList str xs = assertEqual str xs []
test1 = TestCase $ assertEqual "" testcase1 assertion1
test2 = TestCase $ assertEqual "" testcase2 assertion2
test3 = TestCase $ assertEmptyList "" testcase3''
tests = TestList [test1, test2, test3]
-- Main
main = runTestTT tests
1. Situation: testcase3 = flatten (List [])
GHCi, version 7.4.2: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
[1 of 1] Compiling Main (problem7.hs, interpreted)
problem7.hs:29:20:
Ambiguous type variable `a0' in the constraints:
(Eq a0)
arising from a use of `assertEmptyList' at problem7.hs:29:20-34
(Show a0)
arising from a use of `assertEmptyList' at problem7.hs:29:20-34
Probable fix: add a type signature that fixes these type variable(s)
In the second argument of `($)', namely
`assertEmptyList "" testcase3'
In the expression: TestCase $ assertEmptyList "" testcase3
In an equation for `test3':
test3 = TestCase $ assertEmptyList "" testcase3
Failed, modules loaded: none.
Prelude>
2. Situation: testcase3 = flatten (List []) :: Eq a => [a]
GHCi, version 7.4.2: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
[1 of 1] Compiling Main (problem7.hs, interpreted)
problem7.hs:22:13:
Ambiguous type variable `a0' in the constraints:
(Eq a0)
arising from an expression type signature at problem7.hs:22:13-44
(Show a0)
arising from a use of `assertEmptyList' at problem7.hs:29:20-34
Possible cause: the monomorphism restriction applied to the following:
testcase3 :: [a0] (bound at problem7.hs:22:1)
Probable fix: give these definition(s) an explicit type signature
or use -XNoMonomorphismRestriction
In the expression: flatten (List []) :: Eq a => [a]
In an equation for `testcase3':
testcase3 = flatten (List []) :: Eq a => [a]
Failed, modules loaded: none.