Safe Haskell | None |
---|---|
Language | Haskell2010 |
Synopsis
- data Focus
- foldFocus :: b -> (Int -> b) -> Focus -> b
- _Focus :: Prism' Focus Int
- _NoFocus :: Prism' Focus ()
- hasFocus :: Focus -> Bool
- unsafeGetFocus :: Focus -> Int
- data FocusList a = FocusList {
- focusListFocus :: !Focus
- focusListLen :: !Int
- focusList :: !(IntMap a)
- lensFocusListLen :: forall a. Lens' (FocusList a) Int
- lensFocusListFocus :: forall a. Lens' (FocusList a) Focus
- lensFocusList :: forall a a. Lens (FocusList a) (FocusList a) (IntMap a) (IntMap a)
- debugFL :: Show a => FocusList a -> String
- lensFocusListAt :: Int -> Lens' (FocusList a) (Maybe a)
- invariantFL :: FocusList a -> Bool
- unsafeFLFromList :: Focus -> [a] -> FocusList a
- focusItemGetter :: Getter (FocusList a) (Maybe a)
- flFromList :: Focus -> [a] -> Maybe (FocusList a)
- singletonFL :: a -> FocusList a
- emptyFL :: FocusList a
- isEmptyFL :: FocusList a -> Bool
- appendFL :: FocusList a -> a -> FocusList a
- appendSetFocusFL :: FocusList a -> a -> FocusList a
- prependFL :: a -> FocusList a -> FocusList a
- unsafeGetFLFocus :: FocusList a -> Int
- unsafeGetFLFocusItem :: FocusList a -> a
- getFLFocusItem :: FocusList a -> Maybe a
- unsafeInsertNewFL :: Int -> a -> FocusList a -> FocusList a
- unsafeShiftUpFrom :: forall a. Int -> FocusList a -> FocusList a
- unsafeLookup :: Int -> IntMap a -> a
- lookupFL :: Int -> FocusList a -> Maybe a
- insertFL :: Int -> a -> FocusList a -> Maybe (FocusList a)
- unsafeRemove :: Int -> FocusList a -> FocusList a
- unsafeShiftDownFrom :: forall a. Int -> FocusList a -> FocusList a
- removeFL :: Int -> FocusList a -> Maybe (FocusList a)
- indexOfFL :: Eq a => a -> FocusList a -> Maybe Int
- deleteFL :: forall a. Eq a => a -> FocusList a -> FocusList a
- setFocusFL :: Int -> FocusList a -> Maybe (FocusList a)
- updateFocusFL :: Int -> FocusList a -> Maybe (a, FocusList a)
- findFL :: (Int -> a -> Bool) -> FocusList a -> Maybe (Int, a)
- moveFromToFL :: Show a => Int -> Int -> FocusList a -> Maybe (FocusList a)
Documentation
>>>
:set -XFlexibleContexts
>>>
:set -XScopedTypeVariables
Instances
Eq Focus Source # | |
Ord Focus Source # |
NoFocus < Focus a |
Read Focus Source # | |
Show Focus Source # | |
Generic Focus Source # | |
CoArbitrary Focus Source # | |
Defined in Termonad.FocusList coarbitrary :: Focus -> Gen b -> Gen b # | |
type Rep Focus Source # | |
Defined in Termonad.FocusList |
unsafeGetFocus :: Focus -> Int Source #
FocusList | |
|
Instances
invariantFL :: FocusList a -> Bool Source #
This is an invariant that the FocusList
must always protect.
unsafeFLFromList :: Focus -> [a] -> FocusList a Source #
Unsafely create a FocusList
. This does not check that the focus
actually exists in the list.
>>>
let fl = unsafeFLFromList (Focus 1) [0..2]
>>>
debugFL fl
"FocusList {focusListFocus = Focus 1, focusListLen = 3, focusList = fromList [(0,0),(1,1),(2,2)]}"
>>>
let fl = unsafeFLFromList NoFocus []
>>>
debugFL fl
"FocusList {focusListFocus = NoFocus, focusListLen = 0, focusList = fromList []}"
flFromList :: Focus -> [a] -> Maybe (FocusList a) Source #
Safely create a FocusList
from a list.
>>>
flFromList (Focus 1) ["cat","dog","goat"]
Just (FocusList (Focus 1) ["cat","dog","goat"])
>>>
flFromList NoFocus []
Just (FocusList NoFocus [])
If the Focus
is out of range for the list, then Nothing
will be returned.
>>>
flFromList (Focus (-1)) ["cat","dog","goat"]
Nothing
>>>
flFromList (Focus 3) ["cat","dog","goat"]
Nothing
>>>
flFromList NoFocus ["cat","dog","goat"]
Nothing
singletonFL :: a -> FocusList a Source #
Create a FocusList
with a single element.
>>>
singletonFL "hello"
FocusList (Focus 0) ["hello"]
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
appendSetFocusFL :: FocusList a -> a -> FocusList a Source #
A combination of appendFL
and setFocusFL
.
>>>
let Just fl = flFromList (Focus 1) ["hello", "bye", "tree"]
>>>
appendSetFocusFL fl "pie"
FocusList (Focus 3) ["hello","bye","tree","pie"]
(appendSetFocusFL fl a) ^. lensFocusListFocus /= fl ^. lensFocusListFocus
prependFL :: a -> FocusList a -> FocusList a Source #
Prepend a value to a FocusList
.
This can be thought of as a "cons" operation.
>>>
prependFL "hello" emptyFL
FocusList (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
:
(fl ^. lensFocusListFocus) < (prependFL a fl ^. lensFocusListFocus)
unsafeGetFLFocus :: FocusList a -> Int Source #
unsafeGetFLFocusItem :: FocusList a -> a Source #
getFLFocusItem :: FocusList a -> Maybe a Source #
unsafeInsertNewFL :: Int -> a -> FocusList a -> FocusList a Source #
Unsafely insert a new a
in a FocusList
. This sets the Int
value to
a
. The length of the FocusList
will be increased by 1. The
FocusList
s Focus
is not changed.
If there is some value in the FocusList
already at the Int
, then it will
be overwritten. Also, the Int
is not checked to make sure it is above 0.
This function is meant to be used after unsafeShiftUpFrom
.
>>>
let fl = unsafeShiftUpFrom 2 $ unsafeFLFromList (Focus 1) [0,1,200]
>>>
debugFL $ unsafeInsertNewFL 2 100 fl
"FocusList {focusListFocus = Focus 1, focusListLen = 4, focusList = fromList [(0,0),(1,1),(2,100),(3,200)]}"
>>>
let fl = unsafeFLFromList NoFocus []
>>>
debugFL $ unsafeInsertNewFL 0 100 fl
"FocusList {focusListFocus = NoFocus, focusListLen = 1, focusList = fromList [(0,100)]}"
unsafeShiftUpFrom :: forall a. Int -> FocusList a -> FocusList a Source #
This unsafely shifts all values up in a FocusList
starting at a given
index. It also updates the Focus
of the FocusList
if it has been
shifted. This does not change the length of the FocusList
.
It does not check that the Int
is greater than 0. It also does not check
that there is a Focus
.
EXAMPLES
>>>
let fl = unsafeShiftUpFrom 2 $ unsafeFLFromList (Focus 1) [0,1,200]
>>>
debugFL fl
"FocusList {focusListFocus = Focus 1, focusListLen = 3, focusList = fromList [(0,0),(1,1),(3,200)]}"
>>>
let fl = unsafeShiftUpFrom 1 $ unsafeFLFromList (Focus 1) [0,1,200]
>>>
debugFL fl
"FocusList {focusListFocus = Focus 2, focusListLen = 3, focusList = fromList [(0,0),(2,1),(3,200)]}"
>>>
let fl = unsafeShiftUpFrom 0 $ unsafeFLFromList (Focus 1) [0,1,200]
>>>
debugFL fl
"FocusList {focusListFocus = Focus 2, focusListLen = 3, focusList = fromList [(1,0),(2,1),(3,200)]}"
>>>
let fl = unsafeShiftUpFrom 0 $ unsafeFLFromList (Focus 1) [0,1,200]
>>>
debugFL fl
"FocusList {focusListFocus = Focus 2, focusListLen = 3, focusList = fromList [(1,0),(2,1),(3,200)]}"
unsafeLookup :: Int -> IntMap a -> a Source #
Insert a new value into the FocusList
. The Focus
of the list is
changed appropriately.
>>>
insertFL 0 "hello" emptyFL
Just (FocusList (Focus 0) ["hello"])
>>>
insertFL 0 "hello" (singletonFL "bye")
Just (FocusList (Focus 1) ["hello","bye"])
>>>
insertFL 1 "hello" (singletonFL "bye")
Just (FocusList (Focus 0) ["bye","hello"])
This returns Nothing
if the index at which to insert the new value is
either less than 0 or greater than the length of the list.
>>>
insertFL 100 "hello" emptyFL
Nothing
>>>
insertFL 100 "bye" (singletonFL "hello")
Nothing
>>>
insertFL (-1) "bye" (singletonFL "hello")
Nothing
unsafeRemove :: Int -> FocusList a -> FocusList a Source #
Unsafely remove a value from a FocusList
. It effectively leaves a hole
inside the FocusList
. It updates the length of the FocusList
.
This function does not check that a value actually exists in the
FocusList
. It also does not update the Focus
.
This function does update the length of the FocusList
.
>>>
debugFL $ unsafeRemove 1 $ unsafeFLFromList (Focus 0) [0..2]
"FocusList {focusListFocus = Focus 0, focusListLen = 2, focusList = fromList [(0,0),(2,2)]}"
>>>
debugFL $ unsafeRemove 0 $ unsafeFLFromList (Focus 0) [0..2]
"FocusList {focusListFocus = Focus 0, focusListLen = 2, focusList = fromList [(1,1),(2,2)]}"
Trying to remove the last element is completely safe (unless, of course, it
is the Focus
):
>>>
debugFL $ unsafeRemove 2 $ unsafeFLFromList (Focus 2) [0..2]
"FocusList {focusListFocus = Focus 2, focusListLen = 2, focusList = fromList [(0,0),(1,1)]}"
If this function is passed an empty FocusList
, it will make the length -1.
>>>
debugFL $ unsafeRemove 0 emptyFL
"FocusList {focusListFocus = NoFocus, focusListLen = -1, focusList = fromList []}"
unsafeShiftDownFrom :: forall a. Int -> FocusList a -> FocusList a Source #
This shifts all the values down in a FocusList
starting at a given
index. It does not change the Focus
of the FocusList
. It does not change the
length of the FocusList
.
It does not check that shifting elements down will not overwrite other elements.
This function is meant to be called after unsafeRemove
.
>>>
let fl = unsafeRemove 1 $ unsafeFLFromList (Focus 0) [0..2]
>>>
debugFL $ unsafeShiftDownFrom 1 fl
"FocusList {focusListFocus = Focus 0, focusListLen = 2, focusList = fromList [(0,0),(1,2)]}"
>>>
let fl = unsafeRemove 0 $ unsafeFLFromList (Focus 0) [0..2]
>>>
debugFL $ unsafeShiftDownFrom 0 fl
"FocusList {focusListFocus = Focus 0, focusListLen = 2, focusList = fromList [(0,1),(1,2)]}"
Trying to shift down from the last element after it has been removed is a no-op:
>>>
let fl = unsafeRemove 2 $ unsafeFLFromList (Focus 0) [0..2]
>>>
debugFL $ unsafeShiftDownFrom 2 fl
"FocusList {focusListFocus = Focus 0, focusListLen = 2, focusList = fromList [(0,0),(1,1)]}"
:: 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 = unsafeFLFromList (Focus 1) ["cat","goat","dog","hello"]
>>>
removeFL 2 focusList
Just (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 = unsafeFLFromList (Focus 2) ["cat","goat","dog","hello"]
>>>
removeFL 1 focusList
Just (FocusList (Focus 1) ["cat","dog","hello"])
If we remove the Focus
, then the next item is set to have the Focus
.
>>>
let focusList = unsafeFLFromList (Focus 0) ["cat","goat","dog","hello"]
>>>
removeFL 0 focusList
Just (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 = unsafeFLFromList (Focus 0) ["hello"]
>>>
removeFL 0 focusList
Just (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 = unsafeFLFromList (Focus 0) ["hello"]
>>>
removeFL (-1) focusList
Nothing
>>>
let focusList = unsafeFLFromList (Focus 1) ["hello","bye","cat"]
>>>
removeFL 3 focusList
Nothing
If the FocusList
passed in is Empty
, then Nothing
is returned.
>>>
removeFL 0 emptyFL
Nothing
indexOfFL :: Eq a => a -> FocusList a -> Maybe Int Source #
Find the index of the first element in the FocusList
.
>>>
let Just fl = flFromList (Focus 1) ["hello", "bye", "tree"]
>>>
indexOfFL "hello" fl
Just 0
If more than one element exists, then return the index of the first one.
>>>
let Just fl = flFromList (Focus 1) ["dog", "cat", "cat"]
>>>
indexOfFL "cat" fl
Just 1
If the element doesn't exist, then return Nothing
>>>
let Just fl = flFromList (Focus 1) ["foo", "bar", "baz"]
>>>
indexOfFL "hogehoge" fl
Nothing
deleteFL :: forall a. Eq a => a -> FocusList a -> FocusList a Source #
Delete an element from a FocusList
.
>>>
let Just fl = flFromList (Focus 0) ["hello", "bye", "tree"]
>>>
deleteFL "bye" fl
FocusList (Focus 0) ["hello","tree"]
The focus will be updated if an item before it is deleted.
>>>
let Just fl = flFromList (Focus 1) ["hello", "bye", "tree"]
>>>
deleteFL "hello" fl
FocusList (Focus 0) ["bye","tree"]
If there are multiple matching elements in the FocusList
, remove them all.
>>>
let Just fl = flFromList (Focus 0) ["hello", "bye", "bye"]
>>>
deleteFL "bye" fl
FocusList (Focus 0) ["hello"]
If there are no matching elements, return the original FocusList
.
>>>
let Just fl = flFromList (Focus 2) ["hello", "good", "bye"]
>>>
deleteFL "frog" fl
FocusList (Focus 2) ["hello","good","bye"]
setFocusFL :: Int -> FocusList a -> Maybe (FocusList a) Source #
Set the Focus
for a FocusList
.
This is just like updateFocusFL
, but doesn't return the new focused item.
setFocusFL i fl == fmap snd (updateFocusFL i fl)
updateFocusFL :: Int -> FocusList a -> Maybe (a, FocusList a) Source #
Update the Focus
for a FocusList
and get the new focused element.
>>>
updateFocusFL 1 =<< flFromList (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 emptyFL
Nothing
If the new focus is less than 0, or greater than or equal to the length of
the FocusList
, then return Nothing
.
>>>
updateFocusFL (-1) =<< flFromList (Focus 2) ["hello","bye","dog","cat"]
Nothing
>>>
updateFocusFL 4 =<< flFromList (Focus 2) ["hello","bye","dog","cat"]
Nothing
findFL :: (Int -> a -> Bool) -> FocusList a -> Maybe (Int, a) Source #
Find a value in a FocusList
. Similar to Data.List.
.find
>>>
let Just fl = flFromList (Focus 1) ["hello", "bye", "tree"]
>>>
findFL (\_ a -> a == "hello") fl
Just (0,"hello")
This will only find the first value.
>>>
let Just fl = flFromList (Focus 0) ["hello", "bye", "bye"]
>>>
findFL (\_ a -> a == "bye") fl
Just (1,"bye")
If no values match the comparison, this will return Nothing
.
>>>
let Just fl = flFromList (Focus 1) ["hello", "bye", "parrot"]
>>>
findFL (\_ a -> a == "ball") fl
Nothing
:: 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 = flFromList (Focus 1) ["hello", "bye", "parrot"]
>>>
moveFromToFL 0 1 fl
Just (FocusList (Focus 0) ["bye","hello","parrot"])
The Focus
may not get updated if it is not involved.
>>>
let Just fl = flFromList (Focus 0) ["hello", "bye", "parrot"]
>>>
moveFromToFL 1 2 fl
Just (FocusList (Focus 0) ["hello","parrot","bye"])
If the element with the Focus
is moved, then the Focus
will be updated appropriately.
>>>
let Just fl = flFromList (Focus 2) ["hello", "bye", "parrot"]
>>>
moveFromToFL 2 0 fl
Just (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 = flFromList (Focus 2) ["hello", "bye", "parrot"]
>>>
moveFromToFL 3 0 fl
Nothing
If the new index is out of bounds, then Nothing
wil be returned.
>>>
let Just fl = flFromList (Focus 2) ["hello", "bye", "parrot"]
>>>
moveFromToFL 1 (-1) fl
Nothing