Commit 20e560a7 authored by Przemyslaw Kaminski's avatar Przemyslaw Kaminski

[sigma] highlighting of nodes works now

parent 3b72b59b
Pipeline #3226 failed with stage
in 0 seconds
...@@ -265,10 +265,10 @@ graphViewCpt = R.memo' $ here.component "graphView" cpt where ...@@ -265,10 +265,10 @@ graphViewCpt = R.memo' $ here.component "graphView" cpt where
, selectedNodeIds' , selectedNodeIds'
, showEdges' } , showEdges' }
R.useEffect' $ do -- R.useEffect' $ do
here.log2 "[graphView] selectedNodeIds'" $ A.fromFoldable selectedNodeIds' -- here.log2 "[graphView] selectedNodeIds'" $ A.fromFoldable selectedNodeIds'
let (SigmaxT.Graph { nodes: n }) = transformedGraph -- let (SigmaxT.Graph { nodes: n }) = transformedGraph
here.log2 "[graphView] transformedGraph nodes" $ A.fromFoldable n -- here.log2 "[graphView] transformedGraph nodes" $ A.fromFoldable n
-- | Render -- | Render
-- | -- |
......
...@@ -120,8 +120,8 @@ drawGraphCpt = R.memo' $ here.component "graph" cpt where ...@@ -120,8 +120,8 @@ drawGraphCpt = R.memo' $ here.component "graph" cpt where
} }
pure unit pure unit
newGraph <- Graphology.graphFromSigmaxGraph graph' --newGraph <- Graphology.graphFromSigmaxGraph graph'
Sigmax.refreshData sig newGraph --gmax.refreshData sig newGraph
Sigmax.dependOnSigma (R.readRef sigmaRef) "[graphCpt (Ready)] no sigma" $ \sigma -> do Sigmax.dependOnSigma (R.readRef sigmaRef) "[graphCpt (Ready)] no sigma" $ \sigma -> do
-- bind the click event only initially, when ref was empty -- bind the click event only initially, when ref was empty
...@@ -156,9 +156,10 @@ drawGraphCpt = R.memo' $ here.component "graph" cpt where ...@@ -156,9 +156,10 @@ drawGraphCpt = R.memo' $ here.component "graph" cpt where
Sigma.updateCamera sig { ratio: 1.1, x: 0.0, y: 0.0 } Sigma.updateCamera sig { ratio: 1.1, x: 0.0, y: 0.0 }
-- Reload Sigma on Theme changes -- Reload Sigma on Theme changes
_ <- flip T.listen boxes.theme \{ old, new } -> -- TODO
if (eq old new) then pure unit -- _ <- flip T.listen boxes.theme \{ old, new } ->
else Sigma.proxySetSettings window sig $ sigmaSettings new -- if (eq old new) then pure unit
-- else Sigma.proxySetSettings window sig $ sigmaSettings new
pure unit pure unit
Just _sig -> do Just _sig -> do
......
...@@ -10,14 +10,16 @@ module Gargantext.Components.GraphExplorer.Toolbar.Buttons ...@@ -10,14 +10,16 @@ module Gargantext.Components.GraphExplorer.Toolbar.Buttons
import Prelude import Prelude
import DOM.Simple.Console (log2) import Data.Array as A
import Data.DateTime as DDT import Data.DateTime as DDT
import Data.DateTime.Instant as DDI import Data.DateTime.Instant as DDI
import Data.Either (Either(..)) import Data.Either (Either(..))
import Data.Enum (fromEnum) import Data.Enum (fromEnum)
import Data.Foldable (intercalate) import Data.Foldable (intercalate)
import Data.Maybe (Maybe(..)) import Data.Maybe (Maybe(..))
import Data.Sequence as Seq
import Data.String as DS import Data.String as DS
import DOM.Simple.Console (log2)
import Effect.Aff (launchAff_) import Effect.Aff (launchAff_)
import Effect.Class (liftEffect) import Effect.Class (liftEffect)
import Effect.Now as EN import Effect.Now as EN
...@@ -30,6 +32,7 @@ import Gargantext.Components.GraphExplorer.Resources as Graph ...@@ -30,6 +32,7 @@ import Gargantext.Components.GraphExplorer.Resources as Graph
import Gargantext.Components.GraphExplorer.Types as GET import Gargantext.Components.GraphExplorer.Types as GET
import Gargantext.Components.GraphExplorer.Utils as GEU import Gargantext.Components.GraphExplorer.Utils as GEU
import Gargantext.Hooks.Sigmax as Sigmax import Gargantext.Hooks.Sigmax as Sigmax
import Gargantext.Hooks.Sigmax.Graphology as Graphology
import Gargantext.Hooks.Sigmax.Sigma as Sigma import Gargantext.Hooks.Sigmax.Sigma as Sigma
import Gargantext.Hooks.Sigmax.Types as SigmaxTypes import Gargantext.Hooks.Sigmax.Types as SigmaxTypes
import Gargantext.Sessions (Session) import Gargantext.Sessions (Session)
...@@ -88,10 +91,11 @@ cameraButton { id ...@@ -88,10 +91,11 @@ cameraButton { id
, show $ fromEnum $ DDT.hour nowt , show $ fromEnum $ DDT.hour nowt
, show $ fromEnum $ DDT.minute nowt , show $ fromEnum $ DDT.minute nowt
, show $ fromEnum $ DDT.second nowt ] , show $ fromEnum $ DDT.second nowt ]
edges <- Sigma.getEdges s let graph = Sigma.graph s
nodes <- Sigma.getNodes s edges = Graphology.edges graph
let graphData = GET.GraphData $ hyperdataGraph { edges = map GEU.stEdgeToGET edges nodes = Graphology.nodes graph
, nodes = GEU.normalizeNodes $ map GEU.stNodeToGET nodes } graphData = GET.GraphData $ hyperdataGraph { edges = A.fromFoldable $ Seq.map GEU.stEdgeToGET edges
, nodes = A.fromFoldable $ GEU.normalizeNodes $ Seq.map GEU.stNodeToGET nodes }
let cameras = map Sigma.toCamera $ Sigma.cameras s let cameras = map Sigma.toCamera $ Sigma.cameras s
let camera = case cameras of let camera = case cameras of
[c] -> GET.Camera { ratio: c.ratio, x: c.x, y: c.y } [c] -> GET.Camera { ratio: c.ratio, x: c.x, y: c.y }
......
...@@ -7,12 +7,14 @@ module Gargantext.Components.GraphExplorer.Utils ...@@ -7,12 +7,14 @@ module Gargantext.Components.GraphExplorer.Utils
import Gargantext.Prelude import Gargantext.Prelude
import Data.Array as A import Data.Array as A
import Data.Foldable (maximum, minimum)
import Data.Maybe (Maybe(..)) import Data.Maybe (Maybe(..))
import Data.Newtype (wrap) import Data.Newtype (wrap)
import Data.Sequence as Seq
import Gargantext.Components.GraphExplorer.Types as GET import Gargantext.Components.GraphExplorer.Types as GET
import Gargantext.Hooks.Sigmax.Types as ST import Gargantext.Hooks.Sigmax.Types as ST
import Gargantext.Utils (getter) import Gargantext.Utils (getter)
import Gargantext.Utils.Array as GUA import Gargantext.Utils.Seq as GUS
stEdgeToGET :: Record ST.Edge -> GET.Edge stEdgeToGET :: Record ST.Edge -> GET.Edge
stEdgeToGET { _original } = _original stEdgeToGET { _original } = _original
...@@ -31,15 +33,15 @@ stNodeToGET { id, label, x, y, _original: GET.Node { attributes, size, type_ } } ...@@ -31,15 +33,15 @@ stNodeToGET { id, label, x, y, _original: GET.Node { attributes, size, type_ } }
----------------------------------------------------------------------- -----------------------------------------------------------------------
normalizeNodes :: Array GET.Node -> Array GET.Node normalizeNodes :: Seq.Seq GET.Node -> Seq.Seq GET.Node
normalizeNodes ns = map normalizeNode ns normalizeNodes ns = Seq.map normalizeNode ns
where where
xs = map (\(GET.Node { x }) -> x) ns xs = map (\(GET.Node { x }) -> x) ns
ys = map (\(GET.Node { y }) -> y) ns ys = map (\(GET.Node { y }) -> y) ns
mMinx = GUA.min xs mMinx = minimum xs
mMaxx = GUA.max xs mMaxx = maximum xs
mMiny = GUA.min ys mMiny = minimum ys
mMaxy = GUA.max ys mMaxy = maximum ys
mXrange = do mXrange = do
minx <- mMinx minx <- mMinx
maxx <- mMaxx maxx <- mMaxx
......
...@@ -25,7 +25,7 @@ import Gargantext.Hooks.Sigmax.Types as ST ...@@ -25,7 +25,7 @@ import Gargantext.Hooks.Sigmax.Types as ST
import Gargantext.Utils.Console as C import Gargantext.Utils.Console as C
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Set as GSet import Gargantext.Utils.Set as GSet
import Prelude (Unit, bind, discard, flip, map, not, pure, unit, ($), (&&), (*>), (<<<), (<>), (>>=), (+), (>), negate) import Prelude (Unit, bind, discard, flip, map, not, pure, unit, ($), (&&), (*>), (<<<), (<>), (>>=), (+), (>), negate, (/=), (==), (<$>))
import Reactix as R import Reactix as R
import Toestand as T import Toestand as T
...@@ -229,64 +229,87 @@ performDiff sigma g = do ...@@ -229,64 +229,87 @@ performDiff sigma g = do
traverse_ (Graphology.addEdge sigmaGraph) addEdges traverse_ (Graphology.addEdge sigmaGraph) addEdges
traverse_ (Graphology.removeEdge sigmaGraph) removeEdges traverse_ (Graphology.removeEdge sigmaGraph) removeEdges
traverse_ (Graphology.removeNode sigmaGraph) removeNodes traverse_ (Graphology.removeNode sigmaGraph) removeNodes
Sigma.refresh sigma traverse_ (Graphology.updateEdge sigmaGraph) updateEdges
traverse_ (Graphology.updateNode sigmaGraph) updateNodes
--Sigma.refresh sigma
-- TODO Use FA2Layout here -- TODO Use FA2Layout here
--Sigma.killForceAtlas2 sigma --Sigma.killForceAtlas2 sigma
where where
sigmaGraph = Sigma.graph sigma sigmaGraph = Sigma.graph sigma
{add: Tuple addEdges addNodes, remove: Tuple removeEdges removeNodes} = sigmaDiff sigmaGraph g { add: Tuple addEdges addNodes
, remove: Tuple removeEdges removeNodes
, update: Tuple updateEdges updateNodes } = sigmaDiff sigmaGraph g
-- | Compute a diff between current sigma graph and whatever is set via custom controls -- | Compute a diff between current sigma graph and whatever is set via custom controls
sigmaDiff :: Graphology.Graph -> ST.Graph -> Record ST.SigmaDiff sigmaDiff :: Graphology.Graph -> ST.SGraph -> Record ST.SigmaDiff
sigmaDiff graph g@(ST.Graph {nodes, edges}) = {add, remove, update} sigmaDiff sigmaGraph gControls = { add, remove, update }
where where
add = Tuple addEdges addNodes add = Tuple addEdges addNodes
remove = Tuple removeEdges removeNodes remove = Tuple removeEdges removeNodes
-- TODO update = Tuple updateEdges updateNodes
update = Tuple Seq.empty Seq.empty
addG = ST.edgesFilter (\e -> not (Set.member e.id sigmaEdgeIds)) $ sigmaNodes = Graphology.nodes sigmaGraph
ST.nodesFilter (\n -> not (Set.member n.id sigmaNodeIds)) g sigmaEdges = Graphology.edges sigmaGraph
addEdges = ST.graphEdges addG sigmaNodeIds = Set.fromFoldable $ Seq.map _.id sigmaNodes
addNodes = ST.graphNodes addG sigmaEdgeIds = Set.fromFoldable $ Seq.map _.id sigmaEdges
removeEdges = Set.difference sigmaEdgeIds (Set.fromFoldable $ Seq.map _.id edges) gcNodes = ST.graphNodes gControls
removeNodes = Set.difference sigmaNodeIds (Set.fromFoldable $ Seq.map _.id nodes) gcEdges = ST.graphEdges gControls
gcNodeIds = Seq.map _.id gcNodes
gcEdgeIds = Seq.map _.id gcEdges
sigmaNodeIds = Graphology.nodeIds graph
sigmaEdgeIds = Graphology.edgeIds graph
-- Add nodes/edges which aren't present in `sigmaGraph`, but are
-- in `gControls`
addGC = ST.edgesFilter (\e -> not (Set.member e.id sigmaEdgeIds)) $
ST.nodesFilter (\n -> not (Set.member n.id sigmaNodeIds)) gControls
addEdges = ST.graphEdges addGC
addNodes = ST.graphNodes addGC
-- DEPRECATED -- Remove nodes/edges from `sigmaGraph` which aren't in
-- `gControls`
removeEdges = Set.difference sigmaEdgeIds (Set.fromFoldable gcEdgeIds)
removeNodes = Set.difference sigmaNodeIds (Set.fromFoldable gcNodeIds)
markSelectedEdges :: Sigma.Sigma -> ST.EdgeIds -> ST.EdgesMap -> Effect Unit commonNodeIds = Set.intersection sigmaNodeIds $ Set.fromFoldable gcNodeIds
markSelectedEdges sigma selectedEdgeIds graphEdges = do commonEdgeIds = Set.intersection sigmaEdgeIds $ Set.fromFoldable gcEdgeIds
Graphology.forEachEdge (Sigma.graph sigma) \e -> do sigmaNodeIdsMap = Map.fromFoldable $ Seq.map (\n -> Tuple n.id n) sigmaNodes
case Map.lookup e.id graphEdges of sigmaEdgeIdsMap = Map.fromFoldable $ Seq.map (\e -> Tuple e.id e) sigmaEdges
Nothing -> error $ "Edge id " <> e.id <> " not found in graphEdges map" updateEdges = Seq.filter (\e -> Just e /= Map.lookup e.id sigmaEdgeIdsMap) gcEdges
Just {color} -> do -- Find nodes for which `ST.compareNodes` returns `false`, i.e. nodes differ
let newColor = updateNodes = Seq.filter (\n -> (ST.compareNodes n <$> (Map.lookup n.id sigmaNodeIdsMap)) == Just false) gcNodes
if Set.member e.id selectedEdgeIds then
"#ff0000"
else
color
_ <- pure $ (e .= "color") newColor
pure unit
Sigma.refresh sigma
markSelectedNodes :: Sigma.Sigma -> ST.NodeIds -> ST.NodesMap -> Effect Unit
markSelectedNodes sigma selectedNodeIds graphNodes = do -- DEPRECATED
Graphology.forEachNode (Sigma.graph sigma) \n -> do
case Map.lookup n.id graphNodes of -- markSelectedEdges :: Sigma.Sigma -> ST.EdgeIds -> ST.EdgesMap -> Effect Unit
Nothing -> error $ "Node id " <> n.id <> " not found in graphNodes map" -- markSelectedEdges sigma selectedEdgeIds graphEdges = do
Just {color} -> do -- Graphology.forEachEdge (Sigma.graph sigma) \e -> do
let newColor = -- case Map.lookup e.id graphEdges of
if Set.member n.id selectedNodeIds then -- Nothing -> error $ "Edge id " <> e.id <> " not found in graphEdges map"
"#ff0000" -- Just {color} -> do
else -- let newColor =
color -- if Set.member e.id selectedEdgeIds then
_ <- pure $ (n .= "color") newColor -- "#ff0000"
pure unit -- else
Sigma.refresh sigma -- color
-- _ <- pure $ (e .= "color") newColor
-- pure unit
-- Sigma.refresh sigma
-- markSelectedNodes :: Sigma.Sigma -> ST.NodeIds -> ST.NodesMap -> Effect Unit
-- markSelectedNodes sigma selectedNodeIds graphNodes = do
-- Graphology.forEachNode (Sigma.graph sigma) \n -> do
-- case Map.lookup n.id graphNodes of
-- Nothing -> error $ "Node id " <> n.id <> " not found in graphNodes map"
-- Just {color} -> do
-- let newColor =
-- if Set.member n.id selectedNodeIds then
-- "#ff0000"
-- else
-- color
-- _ <- pure $ (n .= "color") newColor
-- pure unit
-- Sigma.refresh sigma
...@@ -10,6 +10,10 @@ export function _addNode(g, name, n) { ...@@ -10,6 +10,10 @@ export function _addNode(g, name, n) {
return g.addNode(name, n); return g.addNode(name, n);
} }
export function _updateNode(g, name, updater) {
return g.updateNode(name, updater);
}
export function _addEdge(g, source, target, e) { export function _addEdge(g, source, target, e) {
return g.addEdge(source, target, e); return g.addEdge(source, target, e);
} }
......
...@@ -23,7 +23,9 @@ foreign import data Graph :: Type ...@@ -23,7 +23,9 @@ foreign import data Graph :: Type
foreign import _newGraph :: EffectFn1 Unit Graph foreign import _newGraph :: EffectFn1 Unit Graph
foreign import _addNode :: EffectFn3 Graph String (Record Types.Node) String foreign import _addNode :: EffectFn3 Graph String (Record Types.Node) String
foreign import _updateNode :: EffectFn3 Graph String (Record Types.Node -> Record Types.Node) Unit
foreign import _addEdge :: EffectFn4 Graph String String (Record Types.Edge) String foreign import _addEdge :: EffectFn4 Graph String String (Record Types.Edge) String
--foreign import _updateEdge :: EffectFn4 Graph String String (Record Types.Edge) String
foreign import _mapNodes :: forall a. Fn2 Graph (Record Types.Node -> a) (Array a) foreign import _mapNodes :: forall a. Fn2 Graph (Record Types.Node -> a) (Array a)
foreign import _forEachEdge :: EffectFn2 Graph (Record Types.Edge -> Effect Unit) Unit foreign import _forEachEdge :: EffectFn2 Graph (Record Types.Edge -> Effect Unit) Unit
foreign import _mapEdges :: forall a. Fn2 Graph (Record Types.Edge -> a) (Array a) foreign import _mapEdges :: forall a. Fn2 Graph (Record Types.Edge -> a) (Array a)
...@@ -45,6 +47,11 @@ addNode :: Graph -> Record Types.Node -> Effect String ...@@ -45,6 +47,11 @@ addNode :: Graph -> Record Types.Node -> Effect String
addNode g node@{ id } = runEffectFn3 _addNode g id node addNode g node@{ id } = runEffectFn3 _addNode g id node
removeNode :: Graph -> String -> Effect Unit removeNode :: Graph -> String -> Effect Unit
removeNode g nId = pure $ g ... "dropNode" $ [nId] removeNode g nId = pure $ g ... "dropNode" $ [nId]
updateNode :: Graph -> Record Types.Node -> Effect Unit
-- | See Types.compareNodes
updateNode g node@{ id, hidden, highlighted } =
runEffectFn3 _updateNode g id (\n -> n { hidden = hidden
, highlighted = highlighted })
forEachNode :: Graph -> (Record Types.Node -> Effect Unit) -> Effect Unit forEachNode :: Graph -> (Record Types.Node -> Effect Unit) -> Effect Unit
-- TODO Check this: how does FFI translate function of two arguments -- TODO Check this: how does FFI translate function of two arguments
-- into PS \x y ? -- into PS \x y ?
...@@ -56,6 +63,9 @@ addEdge :: Graph -> Record Types.Edge -> Effect String ...@@ -56,6 +63,9 @@ addEdge :: Graph -> Record Types.Edge -> Effect String
addEdge g edge@{ source, target } = runEffectFn4 _addEdge g source target edge addEdge g edge@{ source, target } = runEffectFn4 _addEdge g source target edge
removeEdge :: Graph -> String -> Effect Unit removeEdge :: Graph -> String -> Effect Unit
removeEdge g eId = pure $ g ... "dropEdge" $ [eId] removeEdge g eId = pure $ g ... "dropEdge" $ [eId]
updateEdge :: Graph -> Record Types.Edge -> Effect Unit
updateEdge _ _ = pure unit -- TODO
--updateEdge g edge@{ source, target } = runEffectFn4 _updateEdge g source target edge
forEachEdge :: Graph -> (Record Types.Edge -> Effect Unit) -> Effect Unit forEachEdge :: Graph -> (Record Types.Edge -> Effect Unit) -> Effect Unit
forEachEdge = runEffectFn2 _forEachEdge forEachEdge = runEffectFn2 _forEachEdge
--forEachEdge g fn = pure $ g ... "forEachEdge" $ [\_ e -> fn e] --forEachEdge g fn = pure $ g ... "forEachEdge" $ [\_ e -> fn e]
......
...@@ -203,14 +203,6 @@ function _takeScreenshot(sigma) { ...@@ -203,14 +203,6 @@ function _takeScreenshot(sigma) {
return edges.toDataURL('image/png'); return edges.toDataURL('image/png');
} }
function _getEdges(sigma) {
return sigma.graph.edges();
}
function _getNodes(sigma) {
return sigma.graph.nodes();
}
function _proxySetSettings(window, sigma, settings) { function _proxySetSettings(window, sigma, settings) {
var id = sigma.id; var id = sigma.id;
...@@ -235,8 +227,6 @@ export { _sigma, ...@@ -235,8 +227,6 @@ export { _sigma,
dummy as _bindMouseSelectorPlugin, dummy as _bindMouseSelectorPlugin,
_on, _on,
_takeScreenshot, _takeScreenshot,
_getEdges,
_getNodes,
_proxySetSettings, _proxySetSettings,
_setSettings, _setSettings,
_refresh }; _refresh };
...@@ -5,6 +5,7 @@ import Prelude ...@@ -5,6 +5,7 @@ import Prelude
import DOM.Simple.Types (Element, Window) import DOM.Simple.Types (Element, Window)
import Data.Array as A import Data.Array as A
import Data.Either (Either(..)) import Data.Either (Either(..))
import Data.Function.Uncurried (Fn1, runFn1)
import Data.Maybe (Maybe) import Data.Maybe (Maybe)
import Data.Traversable (traverse_) import Data.Traversable (traverse_)
import Effect (Effect) import Effect (Effect)
...@@ -232,12 +233,6 @@ goToAllCameras s props = traverse_ (goTo props) $ cameras s ...@@ -232,12 +233,6 @@ goToAllCameras s props = traverse_ (goTo props) $ cameras s
takeScreenshot :: Sigma -> Effect String takeScreenshot :: Sigma -> Effect String
takeScreenshot = runEffectFn1 _takeScreenshot takeScreenshot = runEffectFn1 _takeScreenshot
getEdges :: Sigma -> Effect (Array (Record Types.Edge))
getEdges = runEffectFn1 _getEdges
getNodes :: Sigma -> Effect (Array (Record Types.Node))
getNodes = runEffectFn1 _getNodes
-- | FFI -- | FFI
foreign import _sigma :: foreign import _sigma ::
forall a b opts err. forall a b opts err.
...@@ -261,8 +256,6 @@ foreign import _bindMouseSelectorPlugin ...@@ -261,8 +256,6 @@ foreign import _bindMouseSelectorPlugin
(Either err Unit) (Either err Unit)
foreign import _on :: forall e. EffectFn3 Sigma String (EffectFn1 e Unit) Unit foreign import _on :: forall e. EffectFn3 Sigma String (EffectFn1 e Unit) Unit
foreign import _takeScreenshot :: EffectFn1 Sigma String foreign import _takeScreenshot :: EffectFn1 Sigma String
foreign import _getEdges :: EffectFn1 Sigma (Array (Record Types.Edge))
foreign import _getNodes :: EffectFn1 Sigma (Array (Record Types.Node))
foreign import _proxySetSettings foreign import _proxySetSettings
:: forall settings. :: forall settings.
EffectFn3 Window EffectFn3 Window
......
...@@ -70,6 +70,12 @@ type EdgeIds = Set.Set EdgeId ...@@ -70,6 +70,12 @@ type EdgeIds = Set.Set EdgeId
type EdgesMap = Map.Map String (Record Edge) type EdgesMap = Map.Map String (Record Edge)
type NodesMap = Map.Map String (Record Node) type NodesMap = Map.Map String (Record Node)
-- | When comparing nodes, we don't want to compare all fields. Only
-- | some are relevant (when updating sigma graph).
compareNodes :: Record Node -> Record Node -> Boolean
compareNodes n1 n2 = n1.hidden == n2.hidden &&
n1.highlighted == n2.highlighted
emptyEdgeIds :: EdgeIds emptyEdgeIds :: EdgeIds
emptyEdgeIds = Set.empty emptyEdgeIds = Set.empty
emptyNodeIds :: NodeIds emptyNodeIds :: NodeIds
......
module Gargantext.Utils.Array ( module Gargantext.Utils.Array (
max push
, min
, push
, range) where , range) where
import Data.Array as A import Data.Array as A
import Data.Foldable (foldr)
import Data.Int as DI import Data.Int as DI
import Data.Maybe (Maybe(..))
import Data.Ord as Ord
import Effect (Effect) import Effect (Effect)
import Effect.Uncurried (EffectFn2, runEffectFn2) import Effect.Uncurried (EffectFn2, runEffectFn2)
...@@ -20,18 +15,6 @@ push :: forall a. Array a -> a -> Effect Unit ...@@ -20,18 +15,6 @@ push :: forall a. Array a -> a -> Effect Unit
push = runEffectFn2 _push push = runEffectFn2 _push
max :: forall a. Ord a => Array a -> Maybe a
max xs = foldr reducer (A.head xs) xs
where
reducer _ Nothing = Nothing
reducer v (Just acc) = Just $ Ord.max acc v
min :: forall a. Ord a => Array a -> Maybe a
min xs = foldr reducer (A.head xs) xs
where
reducer _ Nothing = Nothing
reducer v (Just acc) = Just $ Ord.min acc v
-- | Create an array containing a range of integers, with given step -- | Create an array containing a range of integers, with given step
range :: Int -> Int -> Int -> Array Int range :: Int -> Int -> Int -> Array Int
range start end step = map (\i -> start + i*step) $ A.range 0 end' range start end step = map (\i -> start + i*step) $ A.range 0 end'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment