2012-02-05 14 views
5

geçen gün vermeden bir fonksiyonun birden çok sürümünü kullanarak bir matris içinde sayıların bir demet toplamak için küçük bir program yazdım i Bu işlev sonra LeftUp ve Rightpolimorfizmi - bir köşede başlayan <code>data Matrix = Matrix [[Int]]</code> - - <code>Corner</code> ve Yol'u takip - <code>[Direction]</code> tüm farklı isimler o

turnLUR :: Transformable a => (Corner, Direction) -> a -> a 

kullanma - üç tip bir sınıf sonra Transformable

ı, belirli bir köşe ve yön döner bir dönüştürme işlevi üreten bir fonksiyon, var örneğidir "Hasat" matris içinde tüm sayılar için:

harvest :: Matrix → [(Corner,Direction)] → [Int] 
harvest _ [] = [] 
harvest (Matrix []) _ = [] 
harvest as (cd:csds) = b ++ harvest (Matrix bs) csds' --cd = (Corner,Direction) 
        where f1 = turnLUR cd -- Matrix -> Matrix 
          f2 = turnLUR cd -- Corner -> Corner 
          f3 = turnLUR cd -- Direction -> Direction 
          Matrix (b:bs) = f1 as -- b = first line of [[Int]] 
          fcfd (c,d) = (f2 c,f3 d) 
          csds' = map fcfd csds 

Şimdi f1, f2 ve f3 yerine bir fonksiyonu kullanımına yazmak zorunda yapmak neden benim sorum f üç kez (! Zihnimde KURU tutarak) - her üç tip Corners, Directions ve Matrix, class Transformable'un örnekleridir.

Bu kodu "aynı" işlevin üç sürümünü yapmaksızın nasıl yazarım?

cevap

11

Bu, monomorphism restriction'dan kaynaklanmaktadır. o açık bir tip imza verin ve aynı fonksiyonu her zaman yeniden mümkün olacak:

harvest :: Matrix → [(Corner,Direction)] → [Int] 
harvest _ [] = [] 
harvest (Matrix []) _ = [] 
harvest as (cd:csds) = b ++ harvest (Matrix bs) csds' --cd = (Corner,Direction) 
        where f :: Transformable a => a -> a 
          f = turnLUR cd 
          Matrix (b:bs) = f as -- b = first line of [[Int]] 
          fcfd (c,d) = (f c,f d) 
          csds' = map fcfd csds 

Alternatif olarak, dosyanın üst kısmında {-# LANGUAGE NoMonomorphismRestriction #-} koyarak kapatabilirsiniz.

Monomorfizma kısıtlaması pek sevilmiyor - GHC kullanım kılavuzu dreaded monomorphism restriction - hatta özellikle paylaşımla ilgili bazı zor köşe durumları var (daha fazla bilgi için bağlandığım viki sayfasına bakın). kaçınır. Bu durumda, yalnızca tip imzasını eklemenizi tavsiye ederim.

+3

Monomorfizma kısıtlamasının yalnızca anlamsız stilde yazılan işlevleri (işlevler olmayan değerlerin yanı sıra) etkilediğini unutmayın, bu nedenle, 'f' açık parametreleri kullanarak tanımladığınızda, kısıtlamadan etkilenmezsiniz. bir tür imza vermeyin. – sepp2k

+0

, bu nedenle, tür imzası için bir işlev belirtilmekte olan 'f :: Transformable a => a -> a' tip imzasıdır; ve o olmadan derleyici 'f'' Matrix -> Matrix' türünde ilk kullanım olduğu için çıkar. Bunu açıklamak için çok teşekkür ederim. Özellikle imzanın bu monomorfizm kısıtlamasını çözebileceğini bilmiyordum. – epsilonhalbe

İlgili konular