2012-07-29 17 views
8

99 haskell problemi yapmaya başladım ve problem 7'daydım ve isimlerim havaya uçuyordu.Monomorfizm kısıtlamasını bana açıklayınız lütfen?

Görünüşe göre, buna bağlı bulunuyor: Ben biraz kafam karıştı çünkü http://www.haskell.org/haskellwiki/Monomorphism_restriction Sadece yapmak istedim

emin bunu doğru anlamış.

durum 1: func a, bir tür def olmadan veya bir katı olmayan tip def ile tanımlanmış ve bir kez kullanıldığında derleyicinin, derleme zamanında türün türünü belirleyen sorunları yoktur.

durum 2: Programda birçok kez kullanılan func a, derleyici, verilen argümanlar için işlevi yeniden oluşturmazsa, türün ne olduğundan% 100 emin olamaz.

Hesaplama kaybından kaçınmak için, ghc programlayıcının düzgün çalışabilmesi için a numaralı ürüne sıkı tipte bir def gerektiğini bildirir. test3 Ben testcase3 iadesi için 2 olası türleri vardı söyleyerek olarak yorumlanır olduğu tanımlandı zaman benim durumda düşünüyorum

, assertEqual (Göster

assertEqual :: (Eq a, Show a) => String -> a -> a -> Assertion 

bir hata başlamıştı tipi def vardır ve Eq) ve nasıl devam edeceğini bilmiyordum.

Bu doğru mu, yoksa tamamen kapalı mıyım?

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 durum: 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 durum: 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. 

cevap

4

O, bu belirsiz çözünürlüğü çok monomorfizm kısıtlama var değil değişkenleri defaulting t şapka derleme başarısızlığına neden olur.

-- This explodes 
-- testcase3 = flatten (List []) 

-- so does this: 
-- testcase3' = flatten (List []) :: Eq a => [a] 

-- this does not 
testcase3'' = flatten (List []) :: Num a => [a] 

flatten :: NestedList a -> [a] 
flatten (Elem x) = [x] 
flatten (List x) = concatMap flatten x 

flattena değişken türü üzerinde hiçbir koşulları anlamına gelir, böylece gibi testcase3 tanımına ile hiçbir problem var, bu polimorfik olurdu.

Ama test3 kullanıldığında bir,

test3 = TestCase $ assertEmptyList "" testcase3 -- '' 

Eğer derleyici tip testcase3 orada kullanılması gerektiğini de öğrenmek zorundadır Şimdi
assertEmptyList :: (Eq a, Show a) => String -> [a] -> Assertion 

kısıtlarını devralır. Türü belirlemek için yeterli bağlam yoktur, bu nedenle derleyici varsayılan olarak tür değişkenini çözmeye çalışır. defaulting rules'a göre, bir bağlam (Eq a, Show a), yalnızca en az bir sayısal sınıf içeren içerikler varsayılan olarak kabul edilebildiğinden, varsayılan olarak çözülemez. Bu nedenle, belirsiz bir tür değişkenden dolayı derleme başarısız olur.

testcase3' ve testcase3'' ancak nedeniyle sol tarafından devralınır tanımı sağ taraftaki kısıtlamalar getirir sentezleme türü imza monomorfizm kısıtlama altında yer almaktadır. Bir onaylamada kullanılıp kullanılmadığına bakılmaksızın, bu nedenle derlenemediği için

İfade türü imzası sayısal bir kısıtlama getirdiğinden, varsayılan olarak [Integer] için varsayılan olarak

testcase3'' varsayılan ayardır. Bu nedenle, tür testcase'' için monomorfize edildiğinde, kısıtlanmış tip değişkeni Integer olarak varsayılana ayarlanır. Daha sonra test3'da kullanıldığı türden bir soru yoktur. ,

testcase3' :: Eq a => [a] 
testcase3' = flatten (List []) 

testcase3'' :: Num a => [a] 
testcase3'' = flatten (List []) 

her iki değerle

yerine sağ tarafına ciltlerinde tip imzaları vermiş olsaydın,

polimorfik değerlere kendi başlarına derlenmiş olurdu, ama hala sadece testcase3'' test3 kullanılabilecek olurdu yalnızca bu, varsayılanlamaya izin vermek için gerekli sayısal kısıtlamayı başlattığı için.