2010-07-23 23 views
5

Ben haskell acemi oldum ve bu soruya bir cevap bulamadım.Haskell: Koşulları olan özel tipler

Koşulları türleri tanımlayabilir miyiz? Örneğin, basit kullanıcı tanımlı veri türü olacaktır:

data MyList = MyList [a] 

ben bir şekilde bu kadar MyList yapıcı unsurların bile sayı ile de listeler alabilir bu kodu değiştirmek mümkün mü? Bir şey

Teşekkür ederiz!

+3

'veri MyList = Liste (a, a)'? –

+0

Alexandre, Listeye ([], []), Listeye ([1], []), Listeye ([1,2,3], [1,2]) izin vermemiş olsa bile 2 geçerli eleman? – Alex

+1

Alexandre, tupleların listesini kastetti: [(a, a)]. Bu sayede a (a) (1,2), (5,2), (2,10) gibi) a sayısına sahip olacaksınız. – sdcvvc

cevap

7

Hayır, yapamazsınız.

Gerçekten gerekliyse, yalnızca kendinize bir kurucu benzeri işlev yazın.

toMyList :: [a] -> MyList 
toMyList l | even (length l) = MyList l 
      | otherwise  = error "Length of list has to be even" 

veya

hata kontrol oluşma olasılığı ise:

toMyList :: [a] -> Maybe MyList 

Ama kullanım örneği bağlı olarak belki türleri üzerinden kendinizi ifade edebilirsiniz (mesela küpe veya iki listeleri) zamanı'- yoluyla daha denetler.

+0

Çok teşekkür ederim! – Alex

3

Bu listenizin bir anda artık iki eleman alır emin olur

data MyList a = MyNil 
       | MyCons a a (MyList a) 

gibi bir şey kullanabilirsiniz. Bu, Alexandre'in yorumuna denktir, ancak bazı ayrıntılara bakmaya değer. o düşünce biraz mevcut liste fonksiyonlarını yeniden mümkün hale

fromMyList :: MyList a -> [a] 
fromMyList MyNil = [] 
fromMyList (MyCons x y rest) = x : y : fromMyList rest 

toMyList :: [a] -> Maybe (MyList a) 
toMyList [] = Just MyNil 
toMyList [_] = Nothing 
toMyList (x:y:rest) = fmap (MyCons x y) (toMyList rest) 

toMyListError :: [a] -> MyList a 
toMyListError [] = MyNil 
toMyListError [_] = error "Length of list has to be even" 
toMyListError (x:y:rest) = MyCons x y (toMyListError rest) 

-- these two may be a bit more difficult to use... 
fromMyListTuple :: MyList a -> [(a,a)] 
fromMyListTuple MyNil = [] 
fromMyListTuple (MyCons x y rest) = (x,y) : fromMyListTuple rest 

toMyListTuple :: [(a,a)] -> MyList a 
toMyListTuple = foldr (\(x,y) -> MyCons x y) MyNil  

gibi bazı/dönüşüme varıncaya fonksiyonları ile birlikte

:

myAppend :: MyList a -> MyList a -> MyList a 
myAppend xs ys = toMyListError (fromMyList xs ++ fromMyList ys) 

Ama bütün bu aslında istediğinize bağlıdır bu listeler ile yapmak için!

Konteynırdaki birçok elemanın özelliklerini bu şekilde belirtebilirsiniz, örneğin bkz. Chris Okasaki'nin çalışması. Diğer koşullar da mümkün olabilir, ancak çoğu durumda Dario'nun yaklaşımıyla daha iyi durumda olacaksınız. Son olarak, eğer türünüzün tamamen polimorfik olması gerekiyorsa, içerdiği elemanların sayısından çok daha fazla bilgiyi gerçekten kullanamayacağınızı unutmayın!