Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
purescript-gargantext
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Grégoire Locqueville
purescript-gargantext
Commits
7e937f5b
Commit
7e937f5b
authored
May 16, 2019
by
James Laver
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
push for anoe
parent
5f21c692
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
265 additions
and
63 deletions
+265
-63
packages.json
.psc-package/local/.set/packages.json
+102
-19
package.json
package.json
+1
-1
packages.dhall
packages.dhall
+30
-9
psc-package.json
psc-package.json
+2
-1
Ajax.purs
src/Gargantext/Components/Search/Ajax.purs
+22
-0
SearchField.purs
src/Gargantext/Components/Search/SearchField.purs
+10
-20
Types.purs
src/Gargantext/Components/Search/Types.purs
+67
-0
SearchBar.purs
src/Gargantext/Pages/Layout/Specs/SearchBar.purs
+21
-12
Types.purs
src/Gargantext/Types.purs
+6
-1
Utils.purs
src/Gargantext/Utils.purs
+4
-0
No files found.
.psc-package/local/.set/packages.json
View file @
7e937f5b
...
...
@@ -125,6 +125,22 @@
"repo"
:
"https://github.com/purescript-contrib/purescript-argonaut-traversals.git"
,
"version"
:
"v7.0.0"
},
"array-views"
:
{
"dependencies"
:
[
"arrays"
,
"control"
,
"foldable-traversable"
,
"generics-rep"
,
"maybe"
,
"nonempty"
,
"prelude"
,
"profunctor"
,
"tuples"
,
"unfoldable"
],
"repo"
:
"https://github.com/klntsky/purescript-array-views.git"
,
"version"
:
"v0.0.2"
},
"arraybuffer"
:
{
"dependencies"
:
[
"arraybuffer-types"
,
...
...
@@ -162,7 +178,7 @@
"unsafe-coerce"
],
"repo"
:
"https://github.com/purescript/purescript-arrays.git"
,
"version"
:
"v5.
2.1
"
"version"
:
"v5.
3.0
"
},
"assert"
:
{
"dependencies"
:
[
...
...
@@ -206,7 +222,7 @@
"node-http"
],
"repo"
:
"https://github.com/oreshinya/purescript-basic-auth.git"
,
"version"
:
"v1.0.
0
"
"version"
:
"v1.0.
1
"
},
"behaviors"
:
{
"dependencies"
:
[
...
...
@@ -311,7 +327,7 @@
"node-process"
],
"repo"
:
"https://github.com/Bucketchain/purescript-bucketchain-logger.git"
,
"version"
:
"v0.
2
.0"
"version"
:
"v0.
3
.0"
},
"bucketchain-simple-api"
:
{
"dependencies"
:
[
...
...
@@ -320,7 +336,7 @@
"simple-json"
],
"repo"
:
"https://github.com/Bucketchain/purescript-bucketchain-simple-api.git"
,
"version"
:
"v0.
3
.0"
"version"
:
"v0.
4
.0"
},
"bucketchain-sslify"
:
{
"dependencies"
:
[
...
...
@@ -427,7 +443,7 @@
"web-html"
],
"repo"
:
"https://github.com/ajnsit/purescript-concur.git"
,
"version"
:
"v0.3.
6
"
"version"
:
"v0.3.
7
"
},
"console"
:
{
"dependencies"
:
[
...
...
@@ -456,7 +472,7 @@
"tuples"
],
"repo"
:
"https://github.com/purescript/purescript-contravariant.git"
,
"version"
:
"v4.0.
0
"
"version"
:
"v4.0.
1
"
},
"control"
:
{
"dependencies"
:
[
...
...
@@ -479,7 +495,7 @@
"node-buffer"
],
"repo"
:
"https://github.com/oreshinya/purescript-crypto.git"
,
"version"
:
"v
1.1
.0"
"version"
:
"v
2.0
.0"
},
"css"
:
{
"dependencies"
:
[
...
...
@@ -880,7 +896,7 @@
"web-html"
],
"repo"
:
"https://github.com/purescript-freedom/purescript-freedom.git"
,
"version"
:
"v1.
0
.0"
"version"
:
"v1.
1
.0"
},
"freedom-portal"
:
{
"dependencies"
:
[
...
...
@@ -985,7 +1001,7 @@
"unfoldable"
],
"repo"
:
"https://github.com/purescript/purescript-gen.git"
,
"version"
:
"v2.1.
0
"
"version"
:
"v2.1.
1
"
},
"generics-rep"
:
{
"dependencies"
:
[
...
...
@@ -1153,6 +1169,13 @@
"repo"
:
"https://github.com/purescript/purescript-identity.git"
,
"version"
:
"v4.1.0"
},
"identy"
:
{
"dependencies"
:
[
"simple-json"
],
"repo"
:
"https://github.com/oreshinya/purescript-identy.git"
,
"version"
:
"v2.0.0"
},
"indexed-monad"
:
{
"dependencies"
:
[
"control"
,
...
...
@@ -1418,7 +1441,15 @@
"tuples"
],
"repo"
:
"https://github.com/cprussin/purescript-monad-logger.git"
,
"version"
:
"v1.1.0"
"version"
:
"v1.2.0"
},
"motsunabe"
:
{
"dependencies"
:
[
"lists"
,
"strings"
],
"repo"
:
"https://github.com/justinwoo/purescript-motsunabe.git"
,
"version"
:
"v1.0.0"
},
"mysql"
:
{
"dependencies"
:
[
...
...
@@ -1427,7 +1458,7 @@
"simple-json"
],
"repo"
:
"https://github.com/oreshinya/purescript-mysql.git"
,
"version"
:
"v2.
0.1
"
"version"
:
"v2.
1.0
"
},
"naporitan"
:
{
"dependencies"
:
[
...
...
@@ -1627,6 +1658,15 @@
"repo"
:
"https://github.com/purescript-node/purescript-node-url.git"
,
"version"
:
"v4.0.0"
},
"nodemailer"
:
{
"dependencies"
:
[
"aff"
,
"node-streams"
,
"simple-json"
],
"repo"
:
"https://github.com/oreshinya/purescript-nodemailer.git"
,
"version"
:
"v2.0.0"
},
"nonempty"
:
{
"dependencies"
:
[
"control"
,
...
...
@@ -1691,7 +1731,7 @@
"unsafe-coerce"
],
"repo"
:
"https://github.com/purescript/purescript-ordered-collections.git"
,
"version"
:
"v1.6.
0
"
"version"
:
"v1.6.
1
"
},
"orders"
:
{
"dependencies"
:
[
...
...
@@ -1777,6 +1817,14 @@
"repo"
:
"https://github.com/felixSchl/purescript-pipes.git"
,
"version"
:
"v6.0.0"
},
"pointed-list"
:
{
"dependencies"
:
[
"prelude"
,
"lists"
],
"repo"
:
"https://github.com/paluh/purescript-pointed-list.git"
,
"version"
:
"v0.3.0"
},
"polyform"
:
{
"dependencies"
:
[
"foreign"
,
...
...
@@ -1946,7 +1994,7 @@
"quickcheck"
],
"repo"
:
"https://github.com/garyb/purescript-quickcheck-laws.git"
,
"version"
:
"v
4
.0.0"
"version"
:
"v
5
.0.0"
},
"random"
:
{
"dependencies"
:
[
...
...
@@ -2020,7 +2068,7 @@
"unsafe-reference"
],
"repo"
:
"https://github.com/spicydonuts/purescript-react-basic-hooks.git"
,
"version"
:
"v0.6.
0
"
"version"
:
"v0.6.
1
"
},
"react-dom"
:
{
"dependencies"
:
[
...
...
@@ -2095,6 +2143,18 @@
"repo"
:
"https://github.com/justinwoo/purescript-redux-devtools.git"
,
"version"
:
"v0.1.0"
},
"refined"
:
{
"dependencies"
:
[
"argonaut"
,
"console"
,
"effect"
,
"generics-rep"
,
"prelude"
,
"typelevel"
],
"repo"
:
"https://github.com/danieljharvey/purescript-refined.git"
,
"version"
:
"v0.1.2"
},
"refs"
:
{
"dependencies"
:
[
"effect"
,
...
...
@@ -2272,7 +2332,7 @@
"variant"
],
"repo"
:
"https://github.com/justinwoo/purescript-simple-json.git"
,
"version"
:
"v5.
0
.0"
"version"
:
"v5.
1
.0"
},
"simple-json-generics"
:
{
"dependencies"
:
[
...
...
@@ -2282,6 +2342,14 @@
"repo"
:
"https://github.com/justinwoo/purescript-simple-json-generics.git"
,
"version"
:
"v0.1.0"
},
"simple-json-utils"
:
{
"dependencies"
:
[
"motsunabe"
,
"simple-json"
],
"repo"
:
"https://github.com/justinwoo/purescript-simple-json-utils.git"
,
"version"
:
"v0.1.0"
},
"sized-vectors"
:
{
"dependencies"
:
[
"arrays"
,
...
...
@@ -2541,13 +2609,14 @@
"record"
],
"repo"
:
"https://github.com/justinwoo/purescript-toppokki.git"
,
"version"
:
"v1.
0
.0"
"version"
:
"v1.
1
.0"
},
"tortellini"
:
{
"dependencies"
:
[
"foreign-object"
,
"integers"
,
"lists"
,
"motsunabe"
,
"numbers"
,
"prelude"
,
"record"
,
...
...
@@ -2557,7 +2626,7 @@
"typelevel-prelude"
],
"repo"
:
"https://github.com/justinwoo/purescript-tortellini.git"
,
"version"
:
"v5.
0
.0"
"version"
:
"v5.
1
.0"
},
"transformers"
:
{
"dependencies"
:
[
...
...
@@ -2678,6 +2747,20 @@
"repo"
:
"https://github.com/purescript-contrib/purescript-unsafe-reference"
,
"version"
:
"v3.0.1"
},
"uri"
:
{
"dependencies"
:
[
"these"
,
"arrays"
,
"profunctor-lenses"
,
"unfoldable"
,
"parsing"
,
"integers"
,
"globals"
,
"generics-rep"
],
"repo"
:
"https://github.com/slamdata/purescript-uri"
,
"version"
:
"v7.0.0"
},
"validation"
:
{
"dependencies"
:
[
"bifunctors"
,
...
...
@@ -2726,7 +2809,7 @@
"nullable"
],
"repo"
:
"https://github.com/purescript-web/purescript-web-events.git"
,
"version"
:
"v2.0.
0
"
"version"
:
"v2.0.
1
"
},
"web-file"
:
{
"dependencies"
:
[
...
...
@@ -2745,7 +2828,7 @@
"web-storage"
],
"repo"
:
"https://github.com/purescript-web/purescript-web-html.git"
,
"version"
:
"v2.0.
0
"
"version"
:
"v2.0.
1
"
},
"web-socket"
:
{
"dependencies"
:
[
...
...
package.json
View file @
7e937f5b
{
"scripts"
:
{
"rebase-set"
:
"spago package-set-upgrade && spago psc-package
insdhall"
,
"rebase-set"
:
"spago package-set-upgrade && spago psc-package
-
insdhall"
,
"rebuild-set"
:
"spago psc-package-insdhall"
,
"install-ps"
:
"psc-package install"
,
"build"
:
"pulp --psc-package browserify -t dist/bundle.js"
,
...
...
packages.dhall
View file @
7e937f5b
...
...
@@ -109,10 +109,10 @@ let additions =
-}
let mkPackage =
https://raw.githubusercontent.com/purescript/package-sets/psc-0.12.
3-20190409
/src/mkPackage.dhall sha256:0b197efa1d397ace6eb46b243ff2d73a3da5638d8d0ac8473e8e4a8fc528cf57
https://raw.githubusercontent.com/purescript/package-sets/psc-0.12.
5-20190508
/src/mkPackage.dhall sha256:0b197efa1d397ace6eb46b243ff2d73a3da5638d8d0ac8473e8e4a8fc528cf57
let upstream =
https://raw.githubusercontent.com/purescript/package-sets/psc-0.12.
3-20190409/src/packages.dhall sha256:d327eb707262c9087f8d5caf471690bf69afc8f6307618d9c2ceab13755fb194
https://raw.githubusercontent.com/purescript/package-sets/psc-0.12.
5-20190508/src/packages.dhall sha256:8ef3a6d6d123e05933997426da68ef07289e1cbbdd2a844b5d10c9159deef65a
let overrides =
{ thermite =
...
...
@@ -157,17 +157,33 @@ let additions =
"v3.1.0"
, ffi-simple =
mkPackage
[ "prelude", "effect", "functions", "nullable", "unsafe-coerce" ]
"https://github.com/irresponsible/purescript-ffi-simple"
"v0.2.2"
[ "prelude", "effect", "functions", "nullable", "unsafe-coerce" ]
"https://github.com/irresponsible/purescript-ffi-simple"
"v0.2.2"
, dom-simple =
mkPackage
[ "arrays", "console", "effect", "ffi-simple", "functions", "nullable", "prelude", "unsafe-coerce" ]
"https://github.com/irresponsible/purescript-dom-simple"
"v0.2.4"
[ "arrays"
, "console"
, "effect"
, "ffi-simple"
, "functions"
, "nullable"
, "prelude"
, "unsafe-coerce"
]
"https://github.com/irresponsible/purescript-dom-simple"
"v0.2.4"
, reactix =
mkPackage
[ "console", "dom-simple", "effect", "functions", "nullable", "prelude", "unsafe-coerce", "ffi-simple"]
[ "console"
, "dom-simple"
, "effect"
, "functions"
, "nullable"
, "prelude"
, "unsafe-coerce"
, "ffi-simple"
]
"https://github.com/irresponsible/purescript-reactix"
"v0.2.0"
, uint =
...
...
@@ -175,6 +191,11 @@ let additions =
[ "maybe", "math", "generics-rep" ]
"https://github.com/zaquest/purescript-uint"
"v5.1.1"
, uri =
mkPackage
[ "these", "arrays", "profunctor-lenses", "unfoldable", "parsing", "integers", "globals", "generics-rep" ]
"https://github.com/slamdata/purescript-uri"
"v7.0.0"
}
in upstream // overrides // additions
psc-package.json
View file @
7e937f5b
...
...
@@ -25,6 +25,7 @@
"string-parsers"
,
"prelude"
,
"dom-simple"
,
"reactix"
"reactix"
,
"uri"
]
}
src/Gargantext/Components/Search/Ajax.purs
0 → 100644
View file @
7e937f5b
module Gargantext.Components.Search.Ajax where
import Prelude
import Effect.Class (liftEffect)
import Effect.Aff (Aff)
import Data.Argonaut (class DecodeJson)
import DOM.Simple.Console
import Gargantext.Types (toQuery)
import Gargantext.Components.Search.Types (SearchQuery)
import Gargantext.Config.REST (post)
import Gargantext.Config (justgivemeafuckingurlplease, End(Back))
import URI.Query as Q
searchUrl :: SearchQuery -> String
searchUrl q = justgivemeafuckingurlplease Back $ "search" <> Q.print (toQuery q)
search :: forall a. DecodeJson a => SearchQuery -> Aff a
search q = do
let url = searchUrl q
liftEffect $ log2 "url:" url
post (searchUrl q) q
src/Gargantext/Components/Search/SearchField.purs
View file @
7e937f5b
...
...
@@ -22,16 +22,14 @@ import Reactix.SyntheticEvent as E
select = R.createElement "select"
type Search = {
category :: String,
term :: String }
type Search = { term :: String }
defaultSearch :: Search
defaultSearch = {
category: "PubMed",
term: "" }
defaultSearch = { term: "" }
type Props =
-- list of categories to search, or parsers to use on uploads
( categories :: Array String
-- State hook for a search, how we get data in and out
,
search :: R.State (Maybe Search)
(
search :: R.State (Maybe Search)
)
searchField :: Record Props -> R.Element
...
...
@@ -45,22 +43,13 @@ searchFieldComponent = R.memo (R.hooksComponent "SearchField" cpt) hasChanged
where
cpt props _ = do
let search = maybe defaultSearch identity (fst props.search)
cat <- R.useState $ \_ -> pure search.category
term <- R.useState $ \_ -> pure search.term
pure $
div { className: "search-field" }
[ categoryInput cat props.categories
, searchInput term
, submitButton cat term props.search
[ searchInput term
, submitButton term props.search
]
hasChanged p p' = (p.categories /= p'.categories) || (fst p.search /= fst p.search)
categoryInput :: R.State String -> Array String -> R.Element
categoryInput (cat /\ setCat) cats =
select { className: "category", onChange } (item <$> cats)
where
onChange = mkEffectFn1 $ \e -> setCat (e .. "target" .. "value")
item name = option { value: name } [ text name ]
hasChanged p p' = fst p.search /= fst p'.search
searchInput :: R.State String -> R.Element
searchInput (term /\ setTerm) =
...
...
@@ -71,10 +60,11 @@ searchInput (term /\ setTerm) =
where onChange = mkEffectFn1 $ \e -> setTerm $ e .. "target" .. "value"
submitButton :: R.State String -> R.State
String -> R.State
(Maybe Search) -> R.Element
submitButton (
cat /\ _) (
term /\ _) (_ /\ setSearch) = button { onClick: click } [ text "Search" ]
submitButton :: R.State String -> R.State (Maybe Search) -> R.Element
submitButton (term /\ _) (_ /\ setSearch) = button { onClick: click } [ text "Search" ]
where
click = mkEffectFn1 $ \_ -> do
case term of
"" -> setSearch Nothing
_ -> setSearch $ Just { category: cat, term: term }
_ -> setSearch $ Just { term: term }
src/Gargantext/Components/Search/Types.purs
0 → 100644
View file @
7e937f5b
module Gargantext.Components.Search.Types where
import Control.Monad.Cont.Trans (lift)
import Data.Argonaut (class EncodeJson, jsonEmptyObject, (:=), (~>))
import Data.Maybe (Maybe(..), fromMaybe, maybe)
import Data.Newtype (class Newtype)
import Data.Tuple (Tuple)
import Data.Tuple.Nested ((/\))
import Effect.Aff (Aff)
import Effect.Class (liftEffect)
import Routing.Hash (setHash)
import Thermite (PerformAction, modifyState)
import Gargantext.Prelude
import Gargantext.Types (class ToQuery)
import Gargantext.Config.REST (post)
import Gargantext.Components.Modals.Modal (modalHide)
import Gargantext.Pages.Layout.Specs.AddCorpus.States (Response, State)
import Gargantext.Utils (id)
import URI.Extra.QueryPairs as QP
data SearchOrder
= DateAsc
| DateDesc
| TitleAsc
| TitleDesc
| ScoreAsc
| ScoreDesc
instance showSearchOrder :: Show SearchOrder where
show DateAsc = "DateAsc"
show DateDesc = "DateDesc"
show TitleAsc = "TitleAsc"
show TitleDesc = "TitleDesc"
show ScoreAsc = "ScoreAsc"
show ScoreDesc = "ScoreDesc"
newtype SearchQuery = SearchQuery
{ query :: Array String
, corpus_id :: Maybe Int
, offset :: Maybe Int
, limit :: Maybe Int
, order :: Maybe SearchOrder }
derive instance newtypeSearchQuery :: Newtype SearchQuery _
defaultSearchQuery :: SearchQuery
defaultSearchQuery = SearchQuery
{ query: []
, corpus_id: Nothing
, offset: Nothing
, limit: Nothing
, order: Nothing }
instance searchQueryToQuery :: ToQuery SearchQuery where
toQuery (SearchQuery {offset, limit, order}) =
QP.print id id $ QP.QueryPairs $
pair "offset" offset <> pair "limit" limit <> pair "order" order
where pair :: forall a. Show a => String -> Maybe a -> Array (Tuple QP.Key (Maybe QP.Value))
pair k = maybe [] $ \v ->
[ QP.keyFromString k /\ Just (QP.valueFromString $ show v) ]
instance encodeJsonSearchQuery :: EncodeJson SearchQuery where
encodeJson (SearchQuery {query, corpus_id})
= "query" := query
~> "corpus_id" := fromMaybe 0 corpus_id
~> jsonEmptyObject
src/Gargantext/Pages/Layout/Specs/SearchBar.purs
View file @
7e937f5b
...
...
@@ -3,28 +3,33 @@ module Gargantext.Pages.Layout.Specs.SearchBar
) where
import Prelude
import Control.Monad.Cont.Trans (lift)
import Data.Maybe (Maybe(..))
import Data.Newtype (over)
import Data.Traversable (traverse_)
import Data.Tuple (fst)
import Data.Tuple.Nested ( (/\) )
import Effect.Class (liftEffect)
import Effect.Uncurried (EffectFn1, mkEffectFn1)
import Thermite (Spec, defaultPerformAction, simpleSpec)
import Reactix as R
import DOM.Simple.Console
import Effect.Aff (launchAff)
import Gargantext.Utils.Reactix as R'
import Reactix.DOM.HTML as H
import Gargantext.Components.Search.Types
import Gargantext.Components.Search.Ajax as Ajax
import Gargantext.Components.Modals.Modal (modalShow)
import Gargantext.Components.Search.SearchField (Search, searchField)
import Gargantext.Utils (id)
type Props =
( open :: Boolean
, categories :: Array String )
type Props = ( open :: Boolean )
defaultCategories :: Array String
defaultCategories = ["PubMed", "HAL"]
defaultProps :: Record Props
defaultProps = { open: true, categories: defaultCategories }
defaultProps = { open: true
} --
, categories: defaultCategories }
searchBar :: Record Props -> R.Element
searchBar p = R.createElement searchBarComponent p []
...
...
@@ -38,20 +43,24 @@ searchBarComponent = R.hooksComponent "SearchBar" cpt
onSearchChange search
pure $ H.div { className: "search-bar-container" }
[ toggleButton open
, searchFieldContainer open search
props.categories
]
, searchFieldContainer open search ]
searchFieldContainer :: R.State Boolean -> R.State (Maybe Search) ->
Array String ->
R.Element
searchFieldContainer (true /\ _) search
categories
=
H.div { className: "search-bar open" } [ searchField {
categories,
search } ]
searchFieldContainer (false /\ _) _
_
= H.div {className: "search-bar closed"} []
searchFieldContainer :: R.State Boolean -> R.State (Maybe Search) -> R.Element
searchFieldContainer (true /\ _) search =
H.div { className: "search-bar open" } [ searchField { search } ]
searchFieldContainer (false /\ _) _ = H.div {className: "search-bar closed"} []
onSearchChange :: R.State (Maybe Search) -> R.Hooks Unit
onSearchChange (search /\ setSearch) =
R'.useLayoutEffect1' search $ \_ -> traverse_ triggerSearch search
where
triggerSearch {term, category} = do
log4 "Searching term: " term " in cat:" category
modalShow "addCorpus"
triggerSearch q = do
launchAff $ do
liftEffect $ log2 "Searching term: " q.term
(r :: Unit) <- Ajax.search (searchQuery q)
liftEffect $ log2 "Return:" r
liftEffect $ modalShow "addCorpus"
searchQuery {term} = over SearchQuery (_ {query=[term]}) defaultSearchQuery
toggleButton :: R.State Boolean -> R.Element
toggleButton open =
...
...
src/Gargantext/Types.purs
View file @
7e937f5b
...
...
@@ -4,8 +4,9 @@ import Data.Argonaut ( class DecodeJson, decodeJson, class EncodeJson, encodeJso
, jsonEmptyObject, (:=), (~>), (.?), (.??) )
import Data.Maybe (Maybe(..))
import Data.Either (Either(..))
import Gargantext.Prelude
import Prim.Row (class Union)
import URI.Query (Query)
import Gargantext.Prelude
data TermSize = MonoTerm | MultiTerm
...
...
@@ -13,6 +14,10 @@ data Term = Term String TermList
derive instance eqTermSize :: Eq TermSize
-- | Converts a data structure to a query string
class ToQuery a where
toQuery :: a -> Query
instance showTermSize :: Show TermSize where
show MonoTerm = "MonoTerm"
show MultiTerm = "MultiTerm"
...
...
src/Gargantext/Utils.purs
View file @
7e937f5b
...
...
@@ -7,6 +7,10 @@ import Data.Set as Set
import Data.Set (Set)
import Data.Lens (Lens', lens)
-- | Astonishingly, not in the prelude
id :: forall a. a -> a
id a = a
setterv :: forall nt record field. Newtype nt record => (record -> field -> record) -> field -> nt -> nt
setterv fn v t = (setter (flip fn v) t)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment