2010-02-12 47 views
4

是否有一些Haskell擴展可以創建更復雜的數據構造函數,然後GADT?有沒有辦法在Haskell中做更多的「動態」數據構造函數?

假設我想創建一個數據結構,是一個有序列表,並有類似的數據構造函數(:)與列表工作,具有類型簽名:

data MyOrdList a where 
    (>>>) :: (Ord a) -> a -> MyOrdList a -> MyOrdList a 

但我想(>>>)有一個具體的行爲,這樣的事情:

(>>>) :: (Ord a) => a -> [a] -> [a] 
x >>> [] = [x] 
x >>> xs = low ++ [x] ++ high 
    where low = filter (<x) xs 
     high = filter (>x) xs 

所以結構將永遠是一個有序的結構。 (如果這是一個很好的做法,我現在不會這麼做,我只是提供了我想要的那種行爲的最簡單的例子)。

當然我可以使用函數(>>>),但是我沒有模式匹配和其他好處我會擁有它>>>是一個數據構造函數。

有沒有辦法做到這樣的事情?

回答

3

您可以使:>>>成爲數據構造函數,但是您必須隱藏它才能保持不變。請注意,您可以模式匹配反對在render

​​

然後您可以使用MyOrdList模塊作爲

module Main where 

import Control.Applicative 
import System.IO 

import qualified Data.ByteString as BS 

import MyOrdList 

main = do 
    h <- openBinaryFile "/dev/urandom" ReadMode 
    cs <- readBytes 10 h 
    -- but you cannot write... 
    -- let bad = 3 :>>> 2 :>>> 1 :>>> EmptyOrdList 
    putStrLn (render $ mkMyOrdList cs) 
    where 
    readBytes 0 _ = return [] 
    readBytes n h = do c <- BS.head <$> BS.hGet h 1 
         cs <- readBytes (n-1) h 
         return (c:cs) 

輸出示例:

54 -> 57 -> 64 -> 98 -> 131 -> 146 -> 147 -> 148 -> 190 -> 250 -> <empty>
6

你可以做MyOrdList抽象類型和(>>>)函數和使用視圖模式。爲了簡單起見,我在這裏使用標準列表作爲「後端」。

module MyOrdList 
    (MyOrdList, 
    MyOrdListView (OrdNil, OrdCons), 
    (>>>), 
    emptyOrdList, 
    ordview 
) where 

import Data.List (sort) 

newtype MyOrdList a = List [a] 
    deriving Show 

data MyOrdListView a = OrdNil | OrdCons a (MyOrdList a) 

infixr 5 >>> 

(>>>) :: (Ord a) => a -> MyOrdList a -> MyOrdList a 
x >>> (List xs) = List (sort $ x:xs) 

emptyOrdList = List [] 

ordview :: MyOrdList a -> MyOrdListView a 
ordview (List []) = OrdNil 
ordview (List (x:xs)) = OrdCons x (List xs) 

您可以使用它像:

{-# LANGUAGE ViewPatterns #-} 

import MyOrdList 

ordlength :: MyOrdList a -> Int 
ordlength (ordview -> OrdNil) = 0 
ordlength (ordview -> OrdCons x xs) = 1 + ordlength xs 

作品:

*Main> ordlength $ 2 >>> 3 >>> 1 >>> emptyOrdList 
3 
*Main> 2 >>> 3 >>> 1 >>> emptyOrdList 
List [1,2,3] 

所以你的類型是抽象的,名單隻能由emptyOrdList(>>>)構造,但你仍然有一些模式匹配便利。

相關問題