В Haskell concat лениво строит список, но моя собственная версия с изюминкой, нет

Я пытаюсь создать относительно простую функцию, которая почти совмещает, но с небольшим поворотом. Предполагается, что последний и первый элементы каждого списка двоично или вместе и объединяются в процессе. Я' Я работаю над тем, чтобы научиться писать код, который может использовать возможности Stream Fusion в Data.List.Stream

Я проверил, что concat в базе выполняет то, что необходимо, и лениво строит список, однако эта версия, которую я создал, не работает. т. в базе concat задается следующим образом:

concat :: [[a]] -> [a]
concat = foldr (++) []

(++) :: [a] -> [a] -> [a]
(++) []     ys = ys
(++) (x:xs) ys = x : xs ++ ys

Вот мой код:

bconcat :: [[Word8]] -> [Word8]
bconcat = foldr1 bappend

bappend :: [Word8] -> [Word8] -> [Word8]
bappend as bs = init as ++ (last as .|. head bs) : tail bs

У меня возникает вопрос: как мне написать это, чтобы список строился лениво? Я даже попытался написать bappend, имитируя определение (++) в базе, но это не имело значения.

На данный момент я использую следующий код, он работает так, как я хочу, но производительность отстает от concat. Кроме того, он использует явную рекурсию, которой я бы хотел избежать.

bconcat :: [[Word8]] -> [Word8]
bconcat (a:b:xs) = init a ++ bconcat ((bappend (last a) b):xs)
bconcat (a:[]) = a
bconcat [] = []

bappend :: Word8 -> [Word8] -> [Word8]
bappend !a bs = (a .|. head bs) : tail bs

Итак, у меня возникает вопрос: как мне написать этот код, чтобы он строил список лениво и без явной рекурсии?

Спасибо за ваше время. .

Редактировать:

На данный момент меня больше всего интересует создание чистого, краткого и нестабильного кода с помощью стандартных комбинаторов. Я все еще новичок в функциональном мышлении и хотел бы увидеть достаточно эффективный способ их применения здесь.

7
задан Elriel 19 March 2011 в 20:52
поделиться