2010-02-12 77 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(>>>)构造,但你仍然有一些模式匹配便利。

相关问题