Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
R
rtree
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
chrg
rtree
Commits
865c273e
Commit
865c273e
authored
1 year ago
by
chrg
Browse files
Options
Downloads
Patches
Plain Diff
Cleaning up RTree
parent
4056b202
No related branches found
No related tags found
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
rtree/rtree.cabal
+1
-0
1 addition, 0 deletions
rtree/rtree.cabal
rtree/src/Control/Monad/RTree.hs
+131
-0
131 additions, 0 deletions
rtree/src/Control/Monad/RTree.hs
rtree/src/Control/Monad/Reduce.hs
+24
-153
24 additions, 153 deletions
rtree/src/Control/Monad/Reduce.hs
with
156 additions
and
153 deletions
rtree/rtree.cabal
+
1
−
0
View file @
865c273e
...
...
@@ -11,6 +11,7 @@ build-type: Simple
library
exposed-modules:
Control.Monad.Reduce
Control.Monad.RTree
Control.RTree
Data.Valuation
other-modules:
...
...
This diff is collapsed.
Click to expand it.
rtree/src/Control/Monad/RTree.hs
0 → 100644
+
131
−
0
View file @
865c273e
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UndecidableInstances #-}
-- | A naive implementation of the rtree.
module
Control.Monad.RTree
(
-- * RTree
RTree
,
extract
,
inputs
,
reduce
,
-- * RTreeT and RTreeN
RTreeT
(
..
),
extractT
,
reduceT
,
RTreeN
(
..
),
extractN
,
-- * Re-exports
module
Control
.
Monad
.
Reduce
,
)
where
import
Control.Applicative
import
Control.Monad
import
Control.Monad.Reduce
import
Control.Monad.State
import
qualified
Data.Foldable
as
Foldable
-- | The simple RTree
data
RTree
i
=
Done
!
i
|
Split
(
RTree
i
)
!
(
RTree
i
)
deriving
(
Functor
,
Foldable
)
instance
Applicative
RTree
where
pure
=
Done
(
<*>
)
=
ap
instance
Monad
RTree
where
ma
>>=
f
=
case
ma
of
Done
i
->
f
i
Split
lhs
rhs
->
Split
(
lhs
>>=
f
)
(
rhs
>>=
f
)
instance
MonadReduce
RTree
where
split
=
Split
-- | Extract the top value from the RTree.
extract
::
RTree
i
->
i
extract
=
\
case
Split
_
rhs
->
extract
rhs
Done
i
->
i
{-# INLINE extract #-}
-- | A simple wrapper around @toList@
inputs
::
RTree
i
->
[
i
]
inputs
=
Foldable
.
toList
-- | Reduce the tree
reduce
::
(
MonadPlus
m
)
=>
(
i
->
m
Bool
)
->
RTree
i
->
m
i
reduce
p
=
checkgo
where
checkgo
r
=
do
t
<-
p
(
extract
r
)
guard
t
*>
go
r
go
=
\
case
Done
i
->
pure
i
Split
lhs
rhs
->
checkgo
lhs
<|>
go
rhs
{-# INLINE reduce #-}
-- | An RTreeT Node
data
RTreeN
m
i
=
DoneN
!
i
|
SplitN
!
(
RTreeT
m
i
)
!
(
RTreeN
m
i
)
deriving
(
Functor
,
Foldable
)
newtype
RTreeT
m
i
=
RTreeT
{
unRTreeT
::
m
(
RTreeN
m
i
)}
deriving
(
Functor
,
Foldable
)
instance
(
Monad
m
)
=>
Applicative
(
RTreeT
m
)
where
pure
=
RTreeT
.
pure
.
DoneN
(
<*>
)
=
ap
instance
(
Monad
m
)
=>
Monad
(
RTreeT
m
)
where
RTreeT
ma
>>=
f
=
RTreeT
$
do
ma
>>=
go
where
go
=
\
case
DoneN
i
->
unRTreeT
(
f
i
)
SplitN
lhs
rhs
->
SplitN
(
lhs
>>=
f
)
<$>
go
rhs
instance
(
MonadState
s
m
)
=>
MonadState
s
(
RTreeT
m
)
where
state
f
=
RTreeT
(
DoneN
<$>
state
f
)
-- | Extract a value from an @RTreeT@
extractT
::
(
Functor
m
)
=>
RTreeT
m
b
->
m
b
extractT
(
RTreeT
m
)
=
extractN
<$>
m
{-# INLINE extractT #-}
extractN
::
RTreeN
m
i
->
i
extractN
=
\
case
DoneN
i
->
i
SplitN
_
rhs
->
extractN
rhs
{-# INLINE extractN #-}
-- | Reduction in @RTreeT@
reduceT
::
forall
i
m
n
.
(
Monad
m
,
MonadPlus
n
)
=>
(
forall
a
.
m
a
->
n
a
)
-- ^ A function to lift m into n
->
(
i
->
n
Bool
)
->
RTreeT
m
i
->
n
i
reduceT
lift_
p
=
checkgo
where
checkgo
r
=
do
r'
<-
lift_
(
unRTreeT
r
)
t
<-
p
(
extractN
r'
)
unless
t
mzero
go
r'
go
=
\
case
DoneN
i
->
pure
i
SplitN
lhs
rhs
->
checkgo
lhs
<|>
go
rhs
{-# INLINE reduceT #-}
This diff is collapsed.
Click to expand it.
rtree/src/Control/Monad/Reduce.hs
+
24
−
153
View file @
865c273e
...
...
@@ -3,46 +3,31 @@
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE ViewPatterns #-}
{- |
Module: Control.Monad.Reduce
-}
module
Control.Monad.Reduce
(
-- * MonadReduce
MonadReduce
(
..
),
-- * Constructors
(
<|
),
(
|>
),
splitOn
,
given
,
givenThat
,
givenWith
,
check
,
checkThat
,
conditionalGivenThat
,
-- * Combinators
collect
,
collectReverse
,
collectNonEmpty
,
collectNonEmpty'
,
-- * Algorithms
ddmin
,
linearSearch
,
linearSearch'
,
binarySearch
,
exponentialSearch
,
-- * MonadReducePlus
MonadReducePlus
,
given
,
-- * Helpers
MonadReducePlus
,
onBoth
,
liftMaybe
,
liftMaybeT
,
...
...
@@ -54,127 +39,75 @@ import Control.Monad.Trans.Maybe
import
qualified
Data.List.NonEmpty
as
NE
import
Data.Maybe
import
Control.Monad.State
import
Data.Valuation
(
Truth
(
..
))
import
qualified
Data.Valuation
as
Val
-- {- | A reducer should extract itself
-- @
-- extract . red = id
-- @
-- -}
-- lawReduceId :: (MonadReduce
l
m, Eq i) => (i -> m i) -> i -> Bool
-- lawReduceId :: (MonadReduce m, Eq i) => (i -> m i) -> i -> Bool
-- lawReduceId red i = extract (red i) == i
-- | The Monad Reduce class.
class
(
Monad
m
)
=>
MonadReduce
l
m
|
m
->
l
where
{-# MINIMAL (split
With
| check
With), bottom
#-}
class
(
Monad
m
)
=>
MonadReduce
m
where
{-# MINIMAL (split | check
)
#-}
-- | Split the world into the a reduced world (left) without an element and a world
-- with that element (right). Optionally, labeled with l.
split
With
::
Maybe
(
Truth
l
)
->
m
i
->
m
i
->
m
i
split
With
l
r1
r2
=
check
With
l
>>=
\
case
split
::
m
i
->
m
i
->
m
i
split
r1
r2
=
check
>>=
\
case
False
->
r1
True
->
r2
{-# INLINE split
With
#-}
{-# INLINE split #-}
-- | Check with returns a boolean, that can be used to split the input into a world where
-- the optional truth assignement is satisfiable and where it is not.
checkWith
::
Maybe
(
Truth
l
)
->
m
Bool
checkWith
l
=
splitWith
l
(
pure
False
)
(
pure
True
)
{-# INLINE checkWith #-}
-- | An unrecoverable bottom, which claims that the predicate would always fail on this
-- input.
bottom
::
m
()
-- | Split with no label.
split
::
(
MonadReduce
l
m
)
=>
m
i
->
m
i
->
m
i
split
=
splitWith
Nothing
{-# INLINE split #-}
check
::
m
Bool
check
=
split
(
pure
False
)
(
pure
True
)
{-# INLINE check #-}
-- | Infix split.
(
<|
)
::
(
MonadReduce
l
m
)
=>
m
i
->
m
i
->
m
i
(
<|
)
::
(
MonadReduce
m
)
=>
m
i
->
m
i
->
m
i
(
<|
)
=
split
{-# INLINE (<|) #-}
infixr
3
<|
-- | Infix split, to the right.
(
|>
)
::
(
MonadReduce
l
m
)
=>
m
i
->
m
i
->
m
i
(
|>
)
::
(
MonadReduce
m
)
=>
m
i
->
m
i
->
m
i
r1
|>
r2
=
r2
<|
r1
{-# INLINE (|>) #-}
infixl
3
|>
-- | Split on a label.
splitOn
::
(
MonadReduce
l
m
)
=>
Truth
l
->
m
i
->
m
i
->
m
i
splitOn
l
=
splitWith
(
Just
l
)
{-# INLINE splitOn #-}
-- | Split the world on a fact. False it does not happen, and True it does happen.
check
::
(
MonadReduce
l
m
)
=>
m
Bool
check
=
checkWith
Nothing
{-# INLINE check #-}
type
MonadReducePlus
m
=
(
MonadReduce
m
,
MonadPlus
m
)
-- | Split the world on a labeled fact. False it does not happen, and True it does happen.
checkThat
::
(
MonadReduce
l
m
)
=>
Truth
l
->
m
Bool
checkThat
l
=
checkWith
(
Just
l
)
{-# INLINE checkThat #-}
instance
(
MonadReduce
m
)
=>
MonadReduce
(
MaybeT
m
)
where
split
(
MaybeT
lhs
)
(
MaybeT
rhs
)
=
MaybeT
(
split
lhs
rhs
)
-- | Continues if the fact is true.
given
::
(
MonadReducePlus
l
m
)
=>
m
()
given
=
givenWith
Nothing
given
::
(
MonadReducePlus
m
)
=>
m
()
given
=
split
mzero
(
pure
()
)
{-# INLINE given #-}
-- | Continues if the labeled fact is true.
givenWith
::
(
MonadReducePlus
l
m
)
=>
Maybe
(
Truth
l
)
->
m
()
givenWith
l
=
splitWith
l
mzero
(
pure
()
)
{-# INLINE givenWith #-}
-- | Continues if the labeled fact is true.
givenThat
::
(
MonadReducePlus
l
m
)
=>
Truth
l
->
m
()
givenThat
l
=
givenWith
(
Just
l
)
{-# INLINE givenThat #-}
-- | Given a list of item try to remove each of them from the list.
collect
::
(
MonadReduce
l
m
)
=>
(
a
->
MaybeT
m
b
)
->
[
a
]
->
m
[
b
]
collect
::
(
MonadReduce
m
)
=>
(
a
->
MaybeT
m
b
)
->
[
a
]
->
m
[
b
]
collect
fn
=
fmap
catMaybes
.
traverse
(
runMaybeT
.
fn
)
{-# INLINE collect #-}
-- | Given a list of item try to remove each of them from the list, but from the other direction
collectReverse
::
(
MonadReduce
l
m
)
=>
(
a
->
MaybeT
m
b
)
->
[
a
]
->
m
[
b
]
collectReverse
fn
=
fmap
(
reverse
.
catMaybes
)
.
traverse
(
runMaybeT
.
fn
)
.
reverse
{-# INLINE collectReverse #-}
-- | Given a list of item try to remove each of them, but keep atleast one.
collectNonEmpty'
::
(
MonadReducePlus
l
m
)
=>
(
a
->
m
b
)
->
[
a
]
->
m
[
b
]
collectNonEmpty'
::
(
MonadReducePlus
m
)
=>
(
a
->
m
b
)
->
[
a
]
->
m
[
b
]
collectNonEmpty'
fn
as
=
NE
.
toList
<$>
collectNonEmpty
fn
as
{-# INLINE collectNonEmpty' #-}
-- | Given a list of item try to remove each of them, but keep atleast one.
collectNonEmpty
::
(
MonadReducePlus
l
m
)
=>
(
a
->
m
b
)
->
[
a
]
->
m
(
NE
.
NonEmpty
b
)
collectNonEmpty
::
(
MonadReducePlus
m
)
=>
(
a
->
m
b
)
->
[
a
]
->
m
(
NE
.
NonEmpty
b
)
collectNonEmpty
fn
as
=
do
as'
<-
fmap
catMaybes
.
traverse
(
optional
.
fn
)
$
as
maybe
mzero
pure
$
NE
.
nonEmpty
as'
{-# INLINE collectNonEmpty #-}
conditionalGivenThat
::
(
MonadReducePlus
l
m
)
=>
[
l
]
->
Truth
l
->
m
()
conditionalGivenThat
[]
t
=
givenThat
t
conditionalGivenThat
(
a
:
as
)
t
=
do
splitOn
(
Val
.
is
a
)
(
splitOn
(
Val
.
not
t
)
bottom
mzero
)
(
conditionalGivenThat
as
t
)
type
MonadReducePlus
l
m
=
(
MonadReduce
l
m
,
MonadPlus
m
)
instance
(
MonadReduce
l
m
)
=>
MonadReduce
l
(
MaybeT
m
)
where
bottom
=
MaybeT
{
runMaybeT
=
Just
<$>
bottom
}
splitWith
m
(
MaybeT
lhs
)
(
MaybeT
rhs
)
=
MaybeT
(
splitWith
m
lhs
rhs
)
-- | Helper that lifts a maybe into MonadPlus (or MaybeT)
liftMaybe
::
(
Alternative
m
)
=>
Maybe
a
->
m
a
liftMaybe
=
maybe
empty
pure
...
...
@@ -186,65 +119,3 @@ liftMaybeT m = runMaybeT m >>= liftMaybe
onBoth
::
(
MonadPlus
m
)
=>
m
a
->
m
a
->
(
a
->
a
->
m
a
)
->
m
a
onBoth
mlhs
mrhs
fn
=
join
$
(
fn
<$>
mlhs
<*>
mrhs
)
<|>
fmap
pure
mrhs
<|>
fmap
pure
mlhs
{- | Given a list of ordered options, choose the first that statisfy the constraints,
returning the last element if nothing else matches.
-}
linearSearch
::
(
MonadReduce
l
m
)
=>
NE
.
NonEmpty
i
->
m
i
linearSearch
=
foldr1
(
<|
)
.
fmap
pure
{- | Given a list of ordered options, choose the first that statisfy the
constraints, potentially returning nothing.
-}
linearSearch'
::
(
MonadReduce
l
m
,
MonadPlus
m
)
=>
[
i
]
->
m
i
linearSearch'
is
=
do
mp
<-
linearSearch
(
NE
.
fromList
(
fmap
Just
is
++
[
Nothing
]))
liftMaybe
mp
-- | Given
ddmin
::
(
MonadReduce
l
m
)
=>
[
i
]
->
m
[
i
]
ddmin
=
\
case
[]
->
pure
[]
[
a
]
->
pure
[
a
]
as
->
go
2
as
where
go
n
lst
|
n'
<=
0
=
pure
lst
|
otherwise
=
do
r
<-
runMaybeT
$
linearSearch'
(
partitions
n'
lst
++
composites
n'
lst
)
case
r
of
Nothing
->
go
(
n
*
2
)
lst
<|
pure
lst
-- (for efficiency :D)
Just
lst'
->
ddmin
lst'
where
n'
=
length
lst
`
div
`
n
partitions
n
lst
=
case
lst
of
[]
->
[]
_
->
let
(
h
,
r
)
=
splitAt
n
lst
in
h
:
partitions
n
r
composites
n
lst
=
case
lst
of
[]
->
[]
_
->
let
(
h
,
r
)
=
splitAt
n
lst
in
r
:
fmap
(
h
++
)
(
composites
n
r
)
{- | Given a progression of inputs that are progressively larger, pick the smallest using
binary search.
-}
binarySearch
::
(
MonadReduce
l
m
)
=>
NE
.
NonEmpty
i
->
m
i
binarySearch
=
\
case
a
NE
.:|
[]
->
pure
a
d
->
binarySearch
l
<|
binarySearch
f
where
(
NE
.
fromList
->
f
,
NE
.
fromList
->
l
)
=
NE
.
splitAt
(
NE
.
length
d
`
div
`
2
)
d
{- | Given a progression of inputs that are progressively larger, pick the smallest using
binary search.
-}
exponentialSearch
::
(
MonadReduce
l
m
)
=>
NE
.
NonEmpty
i
->
m
i
exponentialSearch
=
go
1
where
go
n
=
\
case
d
|
n
>=
NE
.
length
d
->
binarySearch
d
|
otherwise
->
go
(
n
*
2
)
l
<|
binarySearch
f
where
(
NE
.
fromList
->
f
,
NE
.
fromList
->
l
)
=
NE
.
splitAt
n
d
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment