Существует определенная структура этой проблемы, и вот она приходит. Я буду использовать этот материал:
import Control.Applicative
import Data.Traversable
import Data.List
Прежде всего, списки-с-дополнения являются полезной концепцией, так что давайте иметь тип для них.
data Padme m = (:-) {padded :: [m], padder :: m} deriving (Show, Eq)
Далее, я помню, что truncating- zip
операция приводит к появлению Applicative
, например, в библиотеке, как newtype ZipList
(популярный пример из не- Monad
). Applicative ZipList
соответствует украшению моноида, заданному бесконечностью и минимумом.Padme
имеет аналогичную структуру, за исключением того, что ее основной моноид - это положительные числа (с бесконечностью), используя один и максимум.
instance Applicative Padme where
pure = ([] :-)
(fs :- f) <*> (ss :- s) = zapp fs ss :- f s where
zapp [] ss = map f ss
zapp fs [] = map ($ s) fs
zapp (f : fs) (s : ss) = f s : zapp fs ss
Я вынужден произнести обычное колдовство для создания по умолчанию Functor
экземпляра.
instance Functor Padme where fmap = (<*>) . pure
Таким образом, мы можем отложить прочь! Например, функция, которая берет оборванный список строк и заполняет их пробелами, становится одним лайнером.
deggar :: [String] -> [String]
deggar = transpose . padded . traverse (:- ' ')
См.?
*Padme> deggar ["om", "mane", "padme", "hum"]
["om ","mane ","padme","hum "]
Не работает с бесконечными списками. – augustss
@ Lee: Извините, мне плохо, да. Он разбивается на бесконечные списки, хотя (даже если он бесконечен), но об этом уже упоминалось. Мой ответ ниже работает с бесконечными и конечными списками. – Clinton