Ленивый vs нетерпеливый анализ и построение списков с двойной связью

Я не могу спать! :)

Я написал небольшой двусвязный список для построения программ на Haskell. Свойством базового языка сделать его было ленивое вычисление (см. Фрагмент кода ниже). И мой вопрос: могу ли я сделать то же самое на чистом функциональном языке с нетерпеливой оценкой или нет? В любом случае, какие свойства активного функционального языка должны иметь возможность построить такую ​​структуру (примесь?)?

import Data.List

data DLList a = DLNull |
    DLNode { prev :: DLList a
           , x :: a
           , next :: DLList a
           }
  deriving (Show)

walkDLList :: (DLList a -> DLList a) -> DLList a -> [a]
walkDLList _ DLNull = []
walkDLList f n@(DLNode _ x _)  = x : walkDLList f (f n)

-- Returns first and last items.
makeDLList :: [a] -> (DLList a, DLList a)
makeDLList xs = let (first, last) = step DLNull xs in (first, last)
  where
    step prev [] = (DLNull, prev)
                         -- Here I use laziness. 'next' is not built yet, it's a thunk.
    step prev (x : xs) = let this = DLNode prev x next 
                             (next, last) = step this xs
                         in (this, last)

testList :: [Int] -> IO ()
testList l = let
    (first, last) = makeDLList l
    byNext = walkDLList next first
    byPrev = walkDLList prev last
  in do
    putStrLn $ "Testing: " ++ show l
    print byNext
    print byPrev

main = do
  testList []
  testList [1, 2, 3, 4]
8
задан Aza 15 April 2013 в 03:39
поделиться