Этот ответ направлен на максимально возможную гибкость при работе со странными условиями (такими как пустые списки) и на построение больших функций из меньших с использованием некоторых библиотечных функций. Это не лучший ответ для кого-то, кто впервые узнает о списках, а скорее пару шагов за этим.
Для следующего вам понадобится
import Control.Monad ((>=>))
и вам нужно будет либо использовать GHC 7.10 и импортировать Data.List (uncons)
, либо определить
uncons :: [a] -> Maybe (a, [a])
uncons [] = Nothing
uncons (x:xs) = Just (x,xs)
Вы можете написать безопасную форму init
, например:
init' :: [x] -> Maybe [x]
init' = foldr go Nothing
where
go x mxs = Just (maybe [] (x:) mxs)
Версия tail
может быть написана
tail' :: [a] -> Maybe [a]
tail' = fmap snd . uncons
Итак, вы можете получить, возможно,
trim' :: [a] -> Maybe [a]
trim' = init' >=> tail'
>=>
является своего рода отсталой монадической композицией. init' >=> tail'
- это функция, которая применяет init'
к своему аргументу для получения Maybe [a]
. Если он получает Nothing
, он возвращает это. Если он получает Just xs
, он применяет tail'
к xs
и возвращает его.
Исходя из этого, вы можете легко создать триммер, который обрезает списки с 0, 1 или 2 элементами до пустых списков:
trim :: [a] -> [a]
trim = maybe [] id . trim'