This module implements lazy construction of strict List. It is not Lazy List implementation and it has different characteristics. It's mostly intended for internal purposes of this library and is exposed just in case some additional user extensions will need it.
Lazy (List a)
LList
uses lazy implementation and therefore can't be compared using ==
empty : LList a
Initialize empty LList
.
toList empty
--> []
singleton : a -> LList a
Initialize singleton LList
.
singleton "foo"
|> toList
--> [ "foo" ]
llist : (a -> List b) -> a -> LList b
Init LList
using constructor.
LList
is initialized using a function from a -> List b
.
Evaluation of this function is lazy and happens in time when
actual value is needed, not when constructor is called.
For instance you can use some List
constructor:
llist (List.range 0) 5
|> toList
--> [ 0, 1, 2, 3, 4, 5 ]
Or use any other function you needList
:
llist (List.filter <| \a -> modBy 2 a == 0) (List.range 0 10)
|> toList
--> [ 0, 2, 4, 6, 8, 10 ]
fromList : List a -> LList a
Construct LList
from List
.
fromList [ "foo", "bar", "baz" ]
|> toList
--> [ "foo", "bar", "baz" ]
cons : a -> LList a -> LList a
Add element to LList
.
empty
|> cons "bar"
|> cons "foo"
|> toList
--> [ "foo", "bar" ]
This function is performed lazily.
append : LList a -> LList a -> LList a
Append LList
to LList
.
append (singleton "foo") (fromList [ "bar", "baz" ])
|> toList
--> [ "foo", "bar", "baz" ]
This function is performed lazily.
isEmpty : LList a -> Basics.Bool
Check if LList
is empty.
isEmpty empty
--> True
isEmpty (singleton "foo")
--> False
llist (List.filter <| \a -> a > 10) [ 1, 2, 3 ]
|> isEmpty
--> True
This function forces evaluation.
toList : LList a -> List a
Build List
from LList
.
toList empty
--> []
toList <| llist (List.range 0) 2
--> [ 0, 1, 2 ]
This function forces evaluation.
head : LList a -> Maybe a
Get the first element from LList
.
head empty
--> Nothing
llist (List.range 0) 2
|> head
--> Just 0
This function forces evaluation.
tail : LList a -> Maybe (LList a)
Get the first element from LList
.
tail empty
--> Nothing
tail (singleton "foo")
|> Maybe.map toList
--> Just []
llist (List.range 0) 2
|> tail
|> Maybe.map toList
--> Just [ 1, 2 ]
This function forces evaluation.
map : (a -> b) -> LList a -> LList b
Map function over LList
.
llist (List.range 0) 5
|> map ((*) 2)
|> toList
--> [ 0, 2, 4, 6, 8, 10 ]
This function is performed lazily.
map2 : (a -> b -> c) -> LList a -> LList b -> LList c
Map a functions over two LList
s.
llist (List.range 0) 5
|> map2 (+) (llist (List.range 0) 5)
|> toList
--> [ 0, 2, 4, 6, 8, 10 ]
This function is performed lazily.
filter : (a -> Basics.Bool) -> LList a -> LList a
Filter LList
.
(cons 1 <| cons 2 <| cons 3 empty)
|> filter ((<) 1)
|> toList
--> [ 2, 3 ]
This function is performed lazily.
filterMap : (a -> Maybe b) -> LList a -> LList b
Similar to List.filterMap
but for LList
.
(cons 1 <| cons 2 <| cons 3 empty)
|> filterMap (\a -> if 1 < a then Just (2 * a) else Nothing)
|> toList
--> [ 4, 6 ]
This function is performed lazily.
reverse : LList a -> LList a
Reverse LList
.
fromList [ 1, 2, 3 ]
|> reverse
|> toList
--> [ 3, 2, 1 ]
This function is performed lazily.
sort : LList comparable -> LList comparable
Sort by for LList
.
fromList [ 3, 1, 2 ]
|> sort
|> toList
--> [ 1, 2, 3 ]
This function is performed lazily.
sortBy : (a -> comparable) -> LList a -> LList a
Sort by for LList
.
fromList [ 3, 1, 2 ]
|> sortBy identity
|> toList
--> [ 1, 2, 3 ]
fromList [ { val = "c"} , { val = "b"}, { val = "a"} ]
|> sortBy .val
|> toList
--> [ { val = "a"}, { val = "b"}, { val = "c"} ]
This function is performed lazily.
sortWith : (a -> a -> Basics.Order) -> LList a -> LList a
Sort with for LList
flippedComparison : comparable -> comparable -> Order
flippedComparison a b =
case Basics.compare a b of
LT -> GT
EQ -> EQ
GT -> LT
llist (List.range 1) 5
|> sortWith flippedComparison
|> toList
--> [ 5, 4, 3, 2, 1 ]
This function is performed lazily.
stableSortWith : (a -> a -> Basics.Order) -> LList a -> LList a
Stable sort with for LList
.
The original order is guaranteed to be kept if the comparison returns EQ
.
compareAge : { r | age : comparable } -> { r | age : comparable } -> Order
compareAge a b =
Basics.compare a.age b.age
fromList [ { name = "Joe", age = 25 }, { name = "Sue", age = 25 }, { name = "Johann", age = 23 } ]
|> stableSortWith compareAge
|> toList
--> [ { name = "Johann", age = 23 }, { name = "Joe", age = 25 }, { name = "Sue", age = 25 } ]
This function is performed lazily.
foldr : (a -> b -> b) -> b -> LList a -> b
Same as List.foldr
but for LLists
.
llist (List.range 0) 5
|> foldr (+) 0
--> 15
llist (List.range 0) 3
|> foldr (::) []
--> [ 0, 1, 2, 3 ]
This function forces evaluation.
foldl : (a -> b -> b) -> b -> LList a -> b
Same as List.foldl
but for LLists
.
llist (List.range 0) 5
|> foldl (+) 0
--> 15
llist (List.range 0) 3
|> foldl (::) []
--> [ 3, 2, 1, 0 ]
This function forces evaluation.
concat : LList (LList a) -> LList a
Flatten LList
.
fromList [ singleton "foo", cons "bar" <| singleton "baz" ]
|> concat
|> toList
--> [ "foo", "bar", "baz" ]
This function is performed lazily.
andThen : (a -> LList b) -> LList a -> LList b
Map LList
construction over LList
.
cons "foo" (cons "bar" <| singleton "baz")
|> andThen (\a -> cons a <| singleton (a ++ " fighter" ))
|> toList
--> [ "foo", "foo fighter", "bar", "bar fighter", "baz", "baz fighter" ]
This function is performed lazily.