2012-04-15 14 views
13

Haskell veri yapıcılarına giriş kontrollerini nasıl ekleyebilirim? ı Haskell veri yapıcılarında giriş kontrolleri

import Data.Time.Calendar 

data SchedulePeriod = SchedulePeriod { startDate :: Day 
    , endDate :: Day 
    , accrualStart :: Day 
    , accrualEnd :: Day 
    , resetDate :: Day 
    , paymentDate :: Day 
    , fraction :: Double } 
    deriving (Show) 

var ve bir kısıtlamayı startDate < endDate empoze etmek istediğinizi varsayalım. Soyut bir veri türü oluşturmadan bunu yapmanın bir yolu var mı?

+0

[olası kısıtlamalarla nasıl yazı yazılır] olası kopyası (http://stackoverflow.com/questions/7978191/how-to-make-a-type-with-restrictions) – ehird

cevap

17

Standart yol, değeri oluşturmadan önce önkoşul kontrol eden ve kullandığı gerçek kurucuyu dışa aktarmayacak bir smart constructor kullanmaktır. Tabii ki, söylediğin gibi bu bir soyut veri türü yaratıyor.

olacağını akıllı yapıcı olmayan Bunu başarmak için tek yol gerçekten kötülük tip sistem hackery (ve standart Day türü kullanmak mümkün olmaz).

+0

Akıllı olarak adlandırılmış parametreleri kullanabilir miyim? kurucular? –

+0

Eğer kayıt sözdizimini taklit ediyorsanız, maalesef değil. Bununla birlikte, akıllı yapıcıya girdi olarak hizmet etmek için başka bir kayıt tanımlayabilirsiniz. Muhtemelen kurucunuzun girdiyi doğrulamaktan daha fazla bir şey yapması durumunda, muhtemelen sadece kopyalamaya değerdir (ör.yardımcı alanların hesaplanması. – ehird

+3

@quant_dev Eğer soyut bir veri türü istemiyor olmanızın sebebi, kuruculardaki desen eşlemesini oluşturabilmeniz için, akıllı kurucuların ikilisini yapabilir ve akıllı yıkıcılar ("belki" ve "ya" gibi) uygulayabilirsiniz. –

13

Ehird'in cevabını kabul edin. Bunu yazıyorum, böylece yorumda bahsettiğim akıllı yıkıcıları açıklayabiliyorum ve bir açıklamada açıklamaya uymayacağım.

data T x y z = A | B x | C y z 

ehird zaten adildir yapıcı, "akıllı" kurucular nasıl sağlanacağı için soyut uzak açıkladı:

Diyelim ki türüne sahip olduğunu varsayalım. Bahsettiğiniz gibi, bu da kurucuları saklamayı gerektirir ve daha sonra bunları desen eşleştirmesi için kullanamazsınız. Ancak bunu, her olası kurucuya karşı desen eşleşmesiyle eşdeğer bir "akıllı" yıkıcıyı kullanarak çözebilirsiniz.

Bunu açıklamak için, kurucular maruz bırakıldı eğer ilk biz T türünde bir işlev yazacağımı nasıl başlayalım:

myFunction :: T x y z -> d 
myFunction t = case t of 
    A  -> f1 
    B x -> f2 x 
    C y z -> f3 y z 

Biz işlevin tip imzadan biliyorum f1, f2 çeşitleri, ve f3 olmalıdır: Yani

f1 :: d 
f2 :: x -> d 
f3 :: y -> z -> d 

biz akıllı yıkıcı olmaya myFunction genelleme olsaydı, biz sadece f1, f2 vegeçmesikendisine parametreler olarak:

smartDestructor :: d -> (x -> d) -> (y -> z -> d) -> t -> d 
smartDestructor f1 f2 f3 t = case t of 
    A  -> f1 
    B x -> f2 x 
    C y z -> f3 y z 

Yani smartDestructor dışa eğer, o zaman insanlar can yapıcıları erişimi gerek kalmadan tip karşı temelde desen maç. Hiç maybe veya either fonksiyonlarını kullandıysanız

, bu durumlarda kurucular gizli olmadıkları halde önce, o zaman, akıllı yıkıcı kullandım, bu yüzden çoğunlukla kolaylık işlevleri olarak verilmektedir:

maybe :: b -> (a -> b) -> Maybe a -> b 
maybe f1 f2 m = case m of 
    Nothing -> f1 
    Just a -> f2 x 

either :: (a -> c) -> (b -> c) -> Either a b -> c 
either f1 f2 e = case e of 
    Left a -> f1 a 
    Right b -> f2 b 
Sizin durumunuzda, akıllı yıkıcının amacı, kurucuları gizleyebilmeniz ve kurucuları ifşa etmemenizdir.
+0

Teşekkürler, çok aydınlatıcı. Keşke iki cevabı kabul edebilseydim ... –

+3

@quant_dev "Akıllı yıkıcılar" için daha iyi bir isim olduğunu öğrendim. Veri tipi "kilise kodlaması" olarak adlandırılır ve herhangi bir veri tipinin bir fonksiyon olarak temsil edilebileceği gerçeğine atıfta bulunur ve bu işlevsel kodlamaya "kilise kodlaması" denir. Gerçekten iyi bir açıklama için şu bağlantıyı kontrol edin: http://web.archiveorange.com/archive/v/nDNOvgzSRV6TNq8KhCgZ –

+0

Teşekkürler, bunu okuyacağım. –