2013-06-23 3 views
9

Ich habe gelesen, dass der unbequeme Typ von take aus historischen Gründen ist, und dass das Ändern könnte dazu führen, dass einige Code zu brechen.Warum kann der Take-Typ nicht geändert werden, um Integral zu verwenden?

Aber kann ich nicht überall take durch genericTake ersetzen, ohne etwas zu brechen? Was ist das Problem?

+0

Ich vermute, dass es eine Situation geben könnte, in der das Ableiten von Typen auf 'take' basiert - mit' genericTake' wird etwas von "can not abzuleiten" auftreten. – leventov

+4

Beachten Sie, dass zusätzlich zu (und vielleicht praktisch relevanterem) Code-Bruch in obskuren Fällen das Ersetzen von 'take' durch' genericTake' in vielen Fällen zu Leistungseinbußen führen würde (da Typ-Default nun zu 'Integer' führt) Wird verwendet, wenn ':: Int' nicht angegeben wird. – sepp2k

Antwort

10

Ein Bruch Fall

genericTake :: Integral i => i -> [a] -> [a] 
genericTake n xs = take (fromIntegral n) xs 

class Foo a where 
    bar :: a -> String 

instance Foo Int where 
    bar _ = "int" 

foo :: String -> [a] -> [a] 
foo ns xs = let y = read ns 
       z = bar y 
      in take y xs 

Das für genericTake brechen.

No instance for (Foo i0) arising from a use of `bar' 
    The type variable `i0' is ambiguous 

Dies ist ein eckt Beispiel, aber Sie können eine Art Schlußfolgerung auf das erste Argument von Take auftretenden verstehen, wo man davon ausgeht, dass es Int ist, jetzt, wenn Sie Typ Integral i => i einige Probleme, wie oben ändern auftreten können.

+0

+1 Dies ist ein echter Schmerz bei Typ-Instanzen, und ich wünschte, es wäre behoben. – jpaugh

+0

@jpaugh Was schlägst du vor, ist eine Lösung? Ich bin mir nicht sicher, ob es behoben werden kann. – Satvik

+0

Habe das nicht versucht, aber würde das nicht mit den erweiterten Standardregeln kompiliert? –

Verwandte Themen