This repository has been archived by the owner on Apr 29, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfinite-list.hs
61 lines (52 loc) · 1.68 KB
/
finite-list.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveFunctor #-}
-- | Lists that are of finite length.
module Data.List.Finite
( FiniteList(Empty, (:%))
, maxed
, cons
, empty
) where
-- | A list of finite length.
data FiniteList a =
FiniteList
{ finiteListMaxLength :: !Int
, finiteList :: ![a]
}
deriving (Functor, Foldable, Traversable)
-- | Make a finite list.
empty :: Int -> FiniteList a
empty size =
FiniteList {finiteListMaxLength = size, finiteListLength = 0, finiteList = []}
-- | Is the list maxed out?
maxed :: FiniteList a -> Bool
maxed (FiniteList {finiteListMaxLength, finiteListLength}) =
finiteListLength == finiteListMaxLength
-- | Cons onto the list. Ignores if we reached the max already.
cons :: a -> FiniteList a -> FiniteList a
cons a list =
if maxed list
then list
else list
{ finiteListLength = finiteListLength list + 1
, finiteList = a : finiteList list
}
-- | Uncons from the list.
uncons :: FiniteList a -> Maybe (a, FiniteList a)
uncons list =
case finiteList list of
(x:xs) ->
let !len = finiteListLength list - 1
in Just (x, list {finiteList = xs, finiteListLength = len})
_ -> Nothing
-- | A bidirectional pattern synonym matching an empty sequence.
pattern Empty :: Int -> FiniteList a
pattern Empty a =
FiniteList {finiteListMaxLength = a, finiteListLength = 0, finiteList = []}
-- | A bidirectional pattern synonym viewing the front of a finite list.
pattern (:%) :: a -> FiniteList a -> FiniteList a
pattern x :% xs <- (uncons -> Just (x, xs))