| Safe Haskell | None |
|---|---|
| Language | Haskell2010 |
Data.FocusList
Contents
Synopsis
- data FocusList a = FocusList {
- focusListFocus :: !Focus
- focusList :: !(Seq a)
- fromListFL :: Focus -> [a] -> Maybe (FocusList a)
- fromFoldableFL :: Foldable f => Focus -> f a -> Maybe (FocusList a)
- toSeqFL :: FocusList a -> Seq a
- lengthFL :: FocusList a -> Int
- isEmptyFL :: FocusList a -> Bool
- getFocusItemFL :: FocusList a -> Maybe a
- lookupFL :: Int -> FocusList a -> Maybe a
- indexOfFL :: Eq a => a -> FocusList a -> Maybe Int
- findFL :: (a -> Bool) -> FocusList a -> Maybe a
- hasFocusFL :: FocusList a -> Bool
- getFocusFL :: FocusList a -> Focus
- prependFL :: a -> FocusList a -> FocusList a
- appendFL :: FocusList a -> a -> FocusList a
- appendSetFocusFL :: FocusList a -> a -> FocusList a
- insertFL :: Int -> a -> FocusList a -> FocusList a
- removeFL :: Int -> FocusList a -> Maybe (FocusList a)
- deleteFL :: forall a. Eq a => a -> FocusList a -> FocusList a
- moveFromToFL :: Show a => Int -> Int -> FocusList a -> Maybe (FocusList a)
- intersperseFL :: a -> FocusList a -> FocusList a
- reverseFL :: FocusList a -> FocusList a
- setFocusFL :: Int -> FocusList a -> Maybe (FocusList a)
- updateFocusFL :: Int -> FocusList a -> Maybe (a, FocusList a)
- sortByFL :: forall a. (a -> a -> Ordering) -> FocusList a -> FocusList a
- emptyFL :: FocusList a
- singletonFL :: a -> FocusList a
- unsafeFromListFL :: Focus -> [a] -> FocusList a
- unsafeGetFocusFL :: FocusList a -> Int
- unsafeGetFocusItemFL :: FocusList a -> a
- invariantFL :: FocusList a -> Bool
- genValidFL :: forall a. Gen a -> Gen (FocusList a)
- lensFocusListFocus :: forall a. Lens' (FocusList a) Focus
- lensFocusList :: forall a a. Lens (FocusList a) (FocusList a) (Seq a) (Seq a)
- data Focus
- hasFocus :: Focus -> Bool
- getFocus :: Focus -> Maybe Int
- maybeToFocus :: Maybe Int -> Focus
- foldFocus :: b -> (Int -> b) -> Focus -> b
- _Focus :: Prism' Focus Int
- _NoFocus :: Prism' Focus ()
- unsafeGetFocus :: Focus -> Int
FocusList
A list with a given element having the Focus.
FocusList has some invariants that must be protected. You should not use
the FocusList constructor or the focusListFocus or focusList
accessors.
Implemented under the hood as a Seq.
Constructors
| FocusList | |
Fields
| |
Instances
Conversions
fromListFL :: Focus -> [a] -> Maybe (FocusList a) Source #
Safely create a FocusList from a list.
>>>fromListFL (Focus 1) ["cat","dog","goat"]Just (FocusList (Focus 1) ["cat","dog","goat"])
>>>fromListFL NoFocus []Just (FocusList NoFocus [])
If the Focus is out of range for the list, then Nothing will be returned.
>>>fromListFL (Focus (-1)) ["cat","dog","goat"]Nothing
>>>fromListFL (Focus 3) ["cat","dog","goat"]Nothing
>>>fromListFL NoFocus ["cat","dog","goat"]Nothing
complexity: O(n) where n is the length of the input list.
Query
lengthFL :: FocusList a -> Int Source #
Return the length of a FocusList.
>>>let Just fl = fromListFL (Focus 2) ["hello", "bye", "parrot"]>>>lengthFL fl3
complexity: O(1)
getFocusItemFL :: FocusList a -> Maybe a Source #
Get the item the FocusList is focusing on. Return Nothing if the
FocusList is empty.
>>>let Just fl = fromListFL (Focus 0) ['a'..'c']>>>getFocusItemFL flJust 'a'
>>>getFocusItemFL emptyFLNothing
This will always return Just if there is a Focus.
hasFocusFL fl ==> isJust (getFocusItemFL fl)
complexity: O(log(min(i, n - i))) where i is the Focus, and n
is the length of the FocusList.
Lookup the element at the specified index, counting from 0.
>>>let Just fl = fromListFL (Focus 0) ['a'..'c']>>>lookupFL 0 flJust 'a'
Returns Nothing if the index is out of bounds.
>>>let Just fl = fromListFL (Focus 0) ['a'..'c']>>>lookupFL 100 flNothing>>>lookupFL (-1) flNothing
Always returns Nothing if the FocusList is empty.
lookupFL i emptyFL == Nothing
complexity: O(log(min(i, n - i))) where i is the index you want to look up, and n
is the length of the FocusList.
indexOfFL :: Eq a => a -> FocusList a -> Maybe Int Source #
Find the index of the first element in the FocusList.
>>>let Just fl = fromListFL (Focus 1) ["hello", "bye", "tree"]>>>indexOfFL "hello" flJust 0
If more than one element exists, then return the index of the first one.
>>>let Just fl = fromListFL (Focus 1) ["dog", "cat", "cat"]>>>indexOfFL "cat" flJust 1
If the element doesn't exist, then return Nothing
>>>let Just fl = fromListFL (Focus 1) ["foo", "bar", "baz"]>>>indexOfFL "hogehoge" flNothing
findFL :: (a -> Bool) -> FocusList a -> Maybe a Source #
Find a value in a FocusList. Similar to Data.List..find
>>>let Just fl = fromListFL (Focus 1) ["hello", "bye", "tree"]>>>findFL (\a -> a == "hello") flJust "hello"
This will only find the first value.
>>>let Just fl = fromListFL (Focus 0) ["hello", "bye", "bye"]>>>findFL (\a -> a == "bye") flJust "bye"
If no values match the comparison, this will return Nothing.
>>>let Just fl = fromListFL (Focus 1) ["hello", "bye", "parrot"]>>>findFL (\a -> a == "ball") flNothing
complexity: O(n) where n is the length of the FocusList.
Query Focus
hasFocusFL :: FocusList a -> Bool Source #
getFocusFL :: FocusList a -> Focus Source #
Manipulate
prependFL :: a -> FocusList a -> FocusList a Source #
Prepend a value to a FocusList.
This can be thought of as a "cons" operation.
>>>prependFL "hello" emptyFLFocusList (Focus 0) ["hello"]
The focus will be updated when prepending:
>>>prependFL "bye" (singletonFL "hello")FocusList (Focus 1) ["bye","hello"]
Prepending to a FocusList will always update the Focus:
getFocusFL fl < getFocusFL (prependFL a fl)
complexity: O(1)
appendFL :: FocusList a -> a -> FocusList a Source #
Append a value to the end of a FocusList.
This can be thought of as a "snoc" operation.
>>>appendFL emptyFL "hello"FocusList (Focus 0) ["hello"]
>>>appendFL (singletonFL "hello") "bye"FocusList (Focus 0) ["hello","bye"]
Appending a value to an empty FocusList is the same as using singletonFL.
appendFL emptyFL a == singletonFL a
complexity: O(log n) where n is the length of the FocusList.
appendSetFocusFL :: FocusList a -> a -> FocusList a Source #
A combination of appendFL and setFocusFL.
>>>let Just fl = fromListFL (Focus 1) ["hello", "bye", "tree"]>>>appendSetFocusFL fl "pie"FocusList (Focus 3) ["hello","bye","tree","pie"]
The Focus will always be updated after calling appendSetFocusFL.
getFocusFL (appendSetFocusFL fl a) > getFocusFL fl
complexity: O(log n) where n is the length of the FocusList.
Arguments
| :: Int | The index at which to insert the new element. |
| -> a | The new element. |
| -> FocusList a | |
| -> FocusList a |
Insert a new value into the FocusList. The Focus of the list is
changed appropriately.
Inserting an element into an empty FocusList will set the Focus on
that element.
>>>insertFL 0 "hello" emptyFLFocusList (Focus 0) ["hello"]
The Focus will not be changed if you insert a new element after the
current Focus.
>>>insertFL 1 "hello" (singletonFL "bye")FocusList (Focus 0) ["bye","hello"]
The Focus will be bumped up by one if you insert a new element before
the current Focus.
>>>insertFL 0 "hello" (singletonFL "bye")FocusList (Focus 1) ["hello","bye"]
Behaves like Data.Sequence.. If the index is out of bounds, it will be
inserted at the nearest available indexinsertAt
>>>insertFL 100 "hello" emptyFLFocusList (Focus 0) ["hello"]
>>>insertFL 100 "bye" (singletonFL "hello")FocusList (Focus 0) ["hello","bye"]
>>>insertFL (-1) "bye" (singletonFL "hello")FocusList (Focus 1) ["bye","hello"]
complexity: O(log(min(i, n - i))) where i is the index you want to insert at, and n
is the length of the FocusList.
Arguments
| :: Int | Index of the element to remove from the |
| -> FocusList a | The |
| -> Maybe (FocusList a) |
Remove an element from a FocusList.
If the element to remove is not the Focus, then update the Focus
accordingly.
For example, if the Focus is on index 1, and we have removed index 2, then
the focus is not affected, so it is not changed.
>>>let focusList = unsafeFromListFL (Focus 1) ["cat","goat","dog","hello"]>>>removeFL 2 focusListJust (FocusList (Focus 1) ["cat","goat","hello"])
If the Focus is on index 2 and we have removed index 1, then the Focus
will be moved back one element to set to index 1.
>>>let focusList = unsafeFromListFL (Focus 2) ["cat","goat","dog","hello"]>>>removeFL 1 focusListJust (FocusList (Focus 1) ["cat","dog","hello"])
If we remove the Focus, then the next item is set to have the Focus.
>>>let focusList = unsafeFromListFL (Focus 0) ["cat","goat","dog","hello"]>>>removeFL 0 focusListJust (FocusList (Focus 0) ["goat","dog","hello"])
If the element to remove is the only element in the list, then the Focus
will be set to NoFocus.
>>>let focusList = unsafeFromListFL (Focus 0) ["hello"]>>>removeFL 0 focusListJust (FocusList NoFocus [])
If the Int for the index to remove is either less than 0 or greater then
the length of the list, then Nothing is returned.
>>>let focusList = unsafeFromListFL (Focus 0) ["hello"]>>>removeFL (-1) focusListNothing
>>>let focusList = unsafeFromListFL (Focus 1) ["hello","bye","cat"]>>>removeFL 3 focusListNothing
If the FocusList passed in is Empty, then Nothing is returned.
>>>removeFL 0 emptyFLNothing
complexity: O(log(min(i, n - i))) where i is index of the element to remove, and n
is the length of the FocusList.
deleteFL :: forall a. Eq a => a -> FocusList a -> FocusList a Source #
Delete an element from a FocusList.
>>>let Just fl = fromListFL (Focus 0) ["hello", "bye", "tree"]>>>deleteFL "bye" flFocusList (Focus 0) ["hello","tree"]
The focus will be updated if an item before it is deleted.
>>>let Just fl = fromListFL (Focus 1) ["hello", "bye", "tree"]>>>deleteFL "hello" flFocusList (Focus 0) ["bye","tree"]
If there are multiple matching elements in the FocusList, remove them all.
>>>let Just fl = fromListFL (Focus 0) ["hello", "bye", "bye"]>>>deleteFL "bye" flFocusList (Focus 0) ["hello"]
If there are no matching elements, return the original FocusList.
>>>let Just fl = fromListFL (Focus 2) ["hello", "good", "bye"]>>>deleteFL "frog" flFocusList (Focus 2) ["hello","good","bye"]
Arguments
| :: Show a | |
| => Int | Index of the item to move. |
| -> Int | New index for the item. |
| -> FocusList a | |
| -> Maybe (FocusList a) |
Move an existing item in a FocusList to a new index.
The Focus gets updated appropriately when moving items.
>>>let Just fl = fromListFL (Focus 1) ["hello", "bye", "parrot"]>>>moveFromToFL 0 1 flJust (FocusList (Focus 0) ["bye","hello","parrot"])
The Focus may not get updated if it is not involved.
>>>let Just fl = fromListFL (Focus 0) ["hello", "bye", "parrot"]>>>moveFromToFL 1 2 flJust (FocusList (Focus 0) ["hello","parrot","bye"])
If the element with the Focus is moved, then the Focus will be updated
appropriately.
>>>let Just fl = fromListFL (Focus 2) ["hello", "bye", "parrot"]>>>moveFromToFL 2 0 flJust (FocusList (Focus 0) ["parrot","hello","bye"])
If the index of the item to move is out bounds, then Nothing will be returned.
>>>let Just fl = fromListFL (Focus 2) ["hello", "bye", "parrot"]>>>moveFromToFL 3 0 flNothing
If the new index is out of bounds, then Nothing wil be returned.
>>>let Just fl = fromListFL (Focus 2) ["hello", "bye", "parrot"]>>>moveFromToFL 1 (-1) flNothing
complexity: O(log n) where n is the length of the FocusList.
intersperseFL :: a -> FocusList a -> FocusList a Source #
Intersperse a new element between existing elements in the FocusList.
>>>let Just fl = fromListFL (Focus 0) ["hello", "bye", "cat"]>>>intersperseFL "foo" flFocusList (Focus 0) ["hello","foo","bye","foo","cat"]
The Focus is updated accordingly.
>>>let Just fl = fromListFL (Focus 2) ["hello", "bye", "cat", "goat"]>>>intersperseFL "foo" flFocusList (Focus 4) ["hello","foo","bye","foo","cat","foo","goat"]
The item with the Focus should never change after calling intersperseFL.
getFocusItemFL (fl :: FocusList Int) == getFocusItemFL (intersperseFL a fl)
intersperseFL should not have any effect on a FocusList with less than
two items.
emptyFL == intersperseFL x emptyFL
singletonFL a == intersperseFL x (singletonFL a)
complexity: O(n) where n is the length of the FocusList.
reverseFL :: FocusList a -> FocusList a Source #
Reverse a FocusList. The Focus is updated accordingly.
>>>let Just fl = fromListFL (Focus 0) ["hello", "bye", "cat"]>>>reverseFL flFocusList (Focus 2) ["cat","bye","hello"]
>>>let Just fl = fromListFL (Focus 2) ["hello", "bye", "cat", "goat"]>>>reverseFL flFocusList (Focus 1) ["goat","cat","bye","hello"]
The item with the Focus should never change after calling intersperseFL.
getFocusItemFL (fl :: FocusList Int) == getFocusItemFL (reverseFL fl)
Reversing twice should not change anything.
(fl :: FocusList Int) == reverseFL (reverseFL fl)
Reversing empty lists and single lists should not do anything.
emptyFL == reverseFL emptyFL
singletonFL a == reverseFL (singletonFL a)
complexity: O(n) where n is the length of the FocusList.
Manipulate Focus
setFocusFL :: Int -> FocusList a -> Maybe (FocusList a) Source #
Set the Focus for a FocusList.
This is just like updateFocusFL, but doesn't return the newly focused item.
setFocusFL i fl == fmap snd (updateFocusFL i fl)
complexity: O(1)
Arguments
| :: Int | The new index to put the |
| -> FocusList a | |
| -> Maybe (a, FocusList a) | A tuple of the new element that gets the |
Update the Focus for a FocusList and get the new focused element.
>>>updateFocusFL 1 =<< fromListFL (Focus 2) ["hello","bye","dog","cat"]Just ("bye",FocusList (Focus 1) ["hello","bye","dog","cat"])
If the FocusList is empty, then return Nothing.
>>>updateFocusFL 1 emptyFLNothing
If the new focus is less than 0, or greater than or equal to the length of
the FocusList, then return Nothing.
>>>updateFocusFL (-1) =<< fromListFL (Focus 2) ["hello","bye","dog","cat"]Nothing
>>>updateFocusFL 4 =<< fromListFL (Focus 2) ["hello","bye","dog","cat"]Nothing
complexity: O(log(min(i, n - i))) where i is the new index to put the Focus on,
and n -- is the length of the FocusList.
Sort
Arguments
| :: (a -> a -> Ordering) | The function to use to compare elements. |
| -> FocusList a | |
| -> FocusList a |
Sort a FocusList.
The Focus will stay with the element that has the Focus.
>>>let Just fl = fromListFL (Focus 2) ["b", "c", "a"]>>>sortByFL compare flFocusList (Focus 0) ["a","b","c"]
Nothing will happen if you try to sort an empty FocusList, or a
FocusList with only one element.
emptyFL == sortByFL compare emptyFL
singletonFL a == sortByFL compare (singletonFL a)
The element with the Focus should be the same before and after sorting.
getFocusItemFL (fl :: FocusList Int) == getFocusItemFL (sortByFL compare fl)
Sorting a FocusList and getting the underlying Seq should be the same as
getting the underlying Seq and then sorting it.
toSeqFL (sortByFL compare (fl :: FocusList Int)) == sortBy compare (toSeqFL fl)
WARNING: The computational complexity for this is very bad. It should be
able to be done in O(n * log n), but the current implementation is
O(n^2) (or worse), where n is the length of the FocusList. This
function could be implemented the same way
Data.Sequence. is implemented. However, a small
change needs to be added to that function to keep track of the sortByFocus in
the FocusList and make sure it gets updated properly. If you're
interested in fixing this, please send a PR.
Construction
singletonFL :: a -> FocusList a Source #
Create a FocusList with a single element.
>>>singletonFL "hello"FocusList (Focus 0) ["hello"]
complexity: O(1)
Unsafe Functions
unsafeFromListFL :: Focus -> [a] -> FocusList a Source #
Unsafely create a FocusList. This does not check that the focus
actually exists in the list. This is an internal function and should
generally not be used. It is only safe to use if you ALREADY know
the Focus is within the list.
Instead, you should generally use fromListFL.
The following is an example of using unsafeFromListFL correctly.
>>>unsafeFromListFL (Focus 1) [0..2]FocusList (Focus 1) [0,1,2]
>>>unsafeFromListFL NoFocus []FocusList NoFocus []
unsafeFromListFL can also be used uncorrectly. The following is an
example of unsafeFromListFL allowing you to create a FocusList that does
not pass invariantFL.
>>>unsafeFromListFL (Focus 100) [0..2]FocusList (Focus 100) [0,1,2]
If fromListFL returns a Just FocusList, then unsafeFromListFL should
return the same FocusList.
complexity: O(n) where n is the length of the input list.
unsafeGetFocusFL :: FocusList a -> Int Source #
Unsafely get the Focus from a FocusList. If the Focus is
NoFocus, this function returns error.
This function is only safe if you already have knowledge that
the FocusList has a Focus.
Generally, getFocusFL should be used instead of this function.
>>>let Just fl = fromListFL (Focus 1) [0..9]>>>unsafeGetFocusFL fl1
>>>unsafeGetFocusFL emptyFL*** Exception: ... ...
complexity: O(1)
unsafeGetFocusItemFL :: FocusList a -> a Source #
Unsafely get the value of the Focus from a FocusList. If the Focus is
NoFocus, this function returns error.
This function is only safe if you already have knowledge that the FocusList
has a Focus.
Generally, getFocusItemFL should be used instead of this function.
>>>let Just fl = fromListFL (Focus 0) ['a'..'c']>>>unsafeGetFocusItemFL fl'a'
>>>unsafeGetFocusFL emptyFL*** Exception: ... ...
complexity: O(log(min(i, n - i))) where i is the Focus, and n
is the length of the FocusList.
Invariants
invariantFL :: FocusList a -> Bool Source #
This is an invariant that the FocusList must always protect.
The functions in this module should generally protect this invariant. If they do not, it is generally a bug.
The invariants are as follows:
- The
Focusin aFocusListcan never be negative. - If there is a
Focus, then it actually exists in theFocusList. - There needs to be a
Focusif the length of theFocusListis greater than 0.
complexity: O(log n), where n is the length of the FocusList.
Testing
Optics
These optics allow you to get/set the internal state of a FocusList.
You should make sure not to directly set the internal state of a
FocusList unless you are sure that the invariants for the FocusList
are protected. See invariantFL.
Focus
The Focus is either NoFocus (if the Focuslist is empty), or Focus
Int to represent focusing on a specific element of the FocusList.
Instances
| Eq Focus Source # | |
| Ord Focus Source # |
NoFocus < Focus a The ordering of (a < b) ==> (Focus a < Focus b) |
| Read Focus Source # | |
| Show Focus Source # | |
| Generic Focus Source # | |
| Arbitrary Focus Source # | |
| CoArbitrary Focus Source # | |
Defined in Data.FocusList Methods coarbitrary :: Focus -> Gen b -> Gen b # | |
| type Rep Focus Source # | |
Defined in Data.FocusList | |
getFocus :: Focus -> Maybe Int Source #
Get the focus index from a Focus.
>>>getFocus (Focus 3)Just 3
>>>getFocus NoFocusNothing
complexity: O(1)
maybeToFocus :: Maybe Int -> Focus Source #
Convert a Maybe Int to a Focus.
>>>maybeToFocus (Just 100)Focus 100
>>>maybeToFocus NothingNoFocus
maybeToFocus and getFocus witness an isomorphism.
focus == maybeToFocus (getFocus focus)
maybeInt == getFocus (maybeToFocus maybeInt)
complexity: O(1)