Bu kodlama hoş bir yolu Data.Foldable tarafından sağlanan kastetmek dayanacağı etmektir.
{-# LANGUAGE DeriveFunctor, DeriveFoldable #-}
import Data.Foldable
import Data.Monoid
Biz otomatik bir uzantı kullanarak bunun bir örneğini elde edebilirsiniz, ama biz bize bir in-sipariş geçişini sağlamak üzere Düğüm yapıcı alanlarını yeniden düzenlemek gerekir.
Biz bunu yaparken, biz yeni veri türünde üzerindeki kısıtlamaları ortadan kaldırmak gerekir. Onlar aslında hiçbir yarar sağlamak ve Haskell 2011 itibarıyla dilinden kaldırıldı (eğer böyle bir sınırlaması kullanmak istediğinizde değil veri türüne, sınıfların örneklerinde koydu olmalıdır.)
data BST a
= Void
| Node
{ left :: BST a
, val :: a
, right :: BST a
} deriving (Eq, Ord, Read, Show, Foldable)
Önce bir için ne anlama geldiğini tanımlamak liste kesinlikle sıralanmasını.
sorted :: Ord a => [a] -> Bool
sorted [] = True
sorted [x] = True
sorted (x:xs) = x < head xs && sorted xs
-- head is safe because of the preceeding match.
Sonra kullanabilirsiniz toListtarafından sağlanan yöntem Data.Foldableve yukarıdaki yardımcı.
isBST :: Ord a => BST a -> Bool
isBST = sorted . toList
İstediğin gibi Ayrıca, daha doğrudan uygulayabilirsiniz. Biz veri türüne sahte kısıtlamalar kaldırıldı yaptığı için, kat tanımını kolaylaştırabilir.
cata :: (b -> a -> b -> b) -> b -> BST a -> b
cata _ z Void = z
cata f z (Node l x r) = f (cata f z l) x (cata f z r)
Şimdi bizim biz ya hiç düğümleri (olması catamorphism, sonucunu modellemek için bir veri türünü gerek Z) veya kesin artan düğümler bir dizi ( T() veya başarısız X)
data T a = Z | T a a | X deriving Eq
Ve sonra uygulayabilirsiniz isBSTdoğrudan
isBST' :: Ord a => BST a -> Bool
isBST' b = cata phi Z b /= X where
phi X _ _ = X
phi _ _ X = X
phi Z a Z = T a a
phi Z a (T b c) = if a < b then T a c else X
phi (T a b) c Z = if b < c then T a c else X
phi (T a b) c (T d e) = if b < c && c < d then T a e else X
Bu biraz sıkıcı, bu yüzden belki de biz geçici devletlere biraz oluşturmak yolu ayrıştırmak için daha iyi olurdu:
cons :: Ord a => a -> T a -> T a
cons _ X = X
cons a Z = T a a
cons a (T b c) = if a < b then T a c else X
instance Ord a => Monoid (T a) where
mempty = Z
Z `mappend` a = a
a `mappend` Z = a
X `mappend` _ = X
_ `mappend` X = X
T a b `mappend` T c d = if b < c then T a d else X
isBST'' :: Ord a => BST a -> Bool
isBST'' b = cata phi Z b /= X where
phi l a r = l `mappend` cons a r
Şahsen, muhtemelen sadece Katlanabilir örneğini kullanmayı tercih ediyorum.