From d74fc4675500ccbbe51d5f487f80919f961356fd Mon Sep 17 00:00:00 2001 From: Orion Kindel Date: Tue, 24 Sep 2024 14:53:59 -0500 Subject: [PATCH] update --- fp/.obsidian/appearance.json | 3 +- fp/.obsidian/graph.json | 2 +- fp/.obsidian/workspace.json | 53 ++++++------- fp/Class/Apply.md | 12 --- fp/Classes/Alternative/Alt.md | 52 ++++++++++++ fp/Classes/Alternative/Alternative.md | 1 + fp/Classes/Alternative/Plus.md | 39 +++++++++ fp/{Class => Classes/Bind}/Bind.md | 0 fp/{Class => Classes/Bind}/Monad.md | 0 fp/{Class => Classes}/Foldable.md | 0 fp/Classes/Functor/Applicative.md | 18 +++++ fp/Classes/Functor/Apply.md | 79 +++++++++++++++++++ fp/{Class => Classes/Functor}/Functor.md | 19 +++-- fp/{Class => Classes}/Math/DivisionRing.md | 0 fp/{Class => Classes}/Math/EuclideanRing.md | 0 fp/{Class => Classes}/Math/Ring.md | 0 fp/{Class => Classes}/Math/Semiring.md | 0 fp/{Class => Classes}/Monoid.md | 0 fp/{Class => Classes}/Semigroup.md | 0 fp/{Class => Classes}/Show.md | 0 fp/{Class/Alt.md => Classes/Traversable.md} | 0 .../Collections/NonEmptyArray.md} | 0 .../Collections/NonEmptyList.md} | 0 fp/{Class/Plus.md => Data/String.md} | 0 .../Infix Operators/Common Operators/Data.md | 1 + fp/Monads/Transformers/ExceptT.md | 0 fp/Monads/Transformers/MaybeT.md | 0 fp/Monads/Transformers/ReaderT.md | 0 fp/Monads/Transformers/StateT.md | 0 fp/Monads/Transformers/WriterT.md | 0 30 files changed, 233 insertions(+), 46 deletions(-) delete mode 100644 fp/Class/Apply.md create mode 100644 fp/Classes/Alternative/Alt.md create mode 100644 fp/Classes/Alternative/Alternative.md create mode 100644 fp/Classes/Alternative/Plus.md rename fp/{Class => Classes/Bind}/Bind.md (100%) rename fp/{Class => Classes/Bind}/Monad.md (100%) rename fp/{Class => Classes}/Foldable.md (100%) create mode 100644 fp/Classes/Functor/Applicative.md create mode 100644 fp/Classes/Functor/Apply.md rename fp/{Class => Classes/Functor}/Functor.md (69%) rename fp/{Class => Classes}/Math/DivisionRing.md (100%) rename fp/{Class => Classes}/Math/EuclideanRing.md (100%) rename fp/{Class => Classes}/Math/Ring.md (100%) rename fp/{Class => Classes}/Math/Semiring.md (100%) rename fp/{Class => Classes}/Monoid.md (100%) rename fp/{Class => Classes}/Semigroup.md (100%) rename fp/{Class => Classes}/Show.md (100%) rename fp/{Class/Alt.md => Classes/Traversable.md} (100%) rename fp/{Class/Alternative.md => Data/Collections/NonEmptyArray.md} (100%) rename fp/{Class/Applicative.md => Data/Collections/NonEmptyList.md} (100%) rename fp/{Class/Plus.md => Data/String.md} (100%) create mode 100644 fp/Monads/Transformers/ExceptT.md create mode 100644 fp/Monads/Transformers/MaybeT.md create mode 100644 fp/Monads/Transformers/ReaderT.md create mode 100644 fp/Monads/Transformers/StateT.md create mode 100644 fp/Monads/Transformers/WriterT.md diff --git a/fp/.obsidian/appearance.json b/fp/.obsidian/appearance.json index 88334d1..5cb9285 100644 --- a/fp/.obsidian/appearance.json +++ b/fp/.obsidian/appearance.json @@ -2,5 +2,6 @@ "theme": "obsidian", "accentColor": "#745eff", "interfaceFontFamily": "", - "baseFontSize": 20 + "baseFontSize": 22, + "nativeMenus": false } \ No newline at end of file diff --git a/fp/.obsidian/graph.json b/fp/.obsidian/graph.json index 2ade83f..9e9cd95 100644 --- a/fp/.obsidian/graph.json +++ b/fp/.obsidian/graph.json @@ -17,6 +17,6 @@ "repelStrength": 10, "linkStrength": 1, "linkDistance": 250, - "scale": 0.6174207201407237, + "scale": 0.36924895020525084, "close": true } \ No newline at end of file diff --git a/fp/.obsidian/workspace.json b/fp/.obsidian/workspace.json index 288c4c8..bbae538 100644 --- a/fp/.obsidian/workspace.json +++ b/fp/.obsidian/workspace.json @@ -4,11 +4,11 @@ "type": "split", "children": [ { - "id": "1ae4bfe7bb551ca1", + "id": "eecc282740820263", "type": "tabs", "children": [ { - "id": "d3a2cb4690ca618a", + "id": "6465d16034124b8f", "type": "leaf", "state": { "type": "graph", @@ -65,8 +65,7 @@ } ], "direction": "horizontal", - "width": 300, - "collapsed": true + "width": 300 }, "right": { "id": "75cf567121b661bb", @@ -141,12 +140,32 @@ "publish:Publish changes...": false } }, - "active": "d3a2cb4690ca618a", + "active": "6465d16034124b8f", "lastOpenFiles": [ + "Classes/Alternative/Alt.md", + "Classes/Alternative/Plus.md", + "Monads/Transformers/MaybeT.md", + "Monads/Transformers/ExceptT.md", + "Monads/Transformers/ReaderT.md", + "Monads/Transformers/WriterT.md", + "Monads/Transformers/StateT.md", + "Monads/Transformers", + "Classes/Alternative/Alternative.md", + "Classes/Functor/Applicative.md", + "Classes/Functor/Apply.md", + "Classes/Functor/Functor.md", + "Classes/Collapsing", + "Classes/Bind", + "Classes/Functor", + "Classes/Alternative", + "Language/Infix Operators/Common Operators/Data.md", + "Classes/Traversable.md", + "Data/Collections/NonEmptyArray.md", + "Data/Collections/NonEmptyList.md", + "Data/String.md", "Data/Collections.md", "Data/Collections/HashMap.md", "Data/Product", - "Data/Untitled.md", "Data/Sum", "Data/Collections/HashSet.md", "Data/Collections/Set.md", @@ -158,27 +177,7 @@ "Language/Row Types/Record.md", "Data/Product/Tuple.md", "Language/Row Types", - "Data/Sum/Either.md", - "Language/Functions.md", - "Language/Functions/Defining/Guard Clause.md", - "Language/Typeclasses.md", - "Language/Type Signature.md", - "Class/Monoid.md", - "Class/Semigroup.md", - "Class/Math/EuclideanRing.md", - "Class/Math/Semiring.md", - "Class/Math/DivisionRing.md", - "Class/Math/Ring.md", - "Class/Semiring.md", - "Class/Math", - "Class/Foldable.md", - "Terminology/Purity.md", - "Language/Expressions/do notation.md", - "Monads/Classes/Stack-safe recursion", - "Monads/Classes/Early Return", - "Monads/Classes/State", - "Monads/Classes/F", - "Monads/Classes/Error Handling", + "Classes/Math", "Untitled 1.canvas", "Untitled.canvas" ] diff --git a/fp/Class/Apply.md b/fp/Class/Apply.md deleted file mode 100644 index fb1c22d..0000000 --- a/fp/Class/Apply.md +++ /dev/null @@ -1,12 +0,0 @@ -Generalizes [[Functor]] to functions with 2+ arguments - -```haskell -apply :: - forall f a b - . Apply f - => f (a -> b) - -> f a - -> f b - -infixl apply as <*> -``` diff --git a/fp/Classes/Alternative/Alt.md b/fp/Classes/Alternative/Alt.md new file mode 100644 index 0000000..4e7a5f9 --- /dev/null +++ b/fp/Classes/Alternative/Alt.md @@ -0,0 +1,52 @@ +Alt is used most often as boolean OR on fallible [[Functor|functors]], but is technically whatever associative operation makes sense for the [[Data Structures|data]] type. + +```haskell +class Functor f <= Alt f where + alt :: forall a. f a -> f a -> f a +``` + +### Examples +In [[Maybe]], Alt allows chainable defaults: +```haskell +Just 1 <|> Just 2 +-- Just 1 + +Nothing <|> Just 1 +-- Just 1 + +Nothing <|> Nothing +-- Nothing + +Nothing <|> Nothing <|> Just 1 +-- Just 1 +``` + +In [[Either]], Alt works as a try/catch: +```haskell +Left "error!" <|> Right "it's ok i recovered" +-- Right "it's ok i recovered" + +Right "i succeeded!" <|> Right "backup" +-- Right "i succeeded!" + +Right unit <|> Left "uh oh!" +-- Right unit + +Left "a" <|> Left "b" +-- Left "b" +``` + +> [!attention] +> Note that Alt in Either takes the last `Left` when all are `Left`! + +In [[Array]], Alt is append: +```haskell +[] <|> [] -- [] + +["a"] <|> [] -- ["a"] + +[] <|> ["a"] -- ["a"] + +["a"] <|> ["b"] -- ["a", "b"] +["a"] <|> ["b", "c"] -- ["a", "b", "c"] +``` \ No newline at end of file diff --git a/fp/Classes/Alternative/Alternative.md b/fp/Classes/Alternative/Alternative.md new file mode 100644 index 0000000..96cc1d7 --- /dev/null +++ b/fp/Classes/Alternative/Alternative.md @@ -0,0 +1 @@ +Doesn't have any class members, just requires that `f` in `Alternative f` must also be [[Plus]] and [[Alt]]. \ No newline at end of file diff --git a/fp/Classes/Alternative/Plus.md b/fp/Classes/Alternative/Plus.md new file mode 100644 index 0000000..c6dd387 --- /dev/null +++ b/fp/Classes/Alternative/Plus.md @@ -0,0 +1,39 @@ +Extends [[Alt]] with an empty value: + +```haskell +class Alt f <= Plus f where + empty :: forall a. f a +``` + +> [!info] +> Conceptually, this lives next to [[Applicative|pure]] in my mind; in [[Maybe]] for example `pure` and `empty` are aliases for `Just` and `Nothing`. + +In [[Array]], `empty` is empty array `[]`. In [[Maybe]], `empty` is `Nothing`. + +The most common place you'll see `empty` is when using [[MaybeT]] as an early return: + +```haskell +logDebug :: String -> Effect Unit +logDebug msg = void $ runMaybeT do + env <- MaybeT $ Process.lookupEnv "NODE_ENV" + when (env /= "DEVELOPMENT") empty + lift $ Console.log msg +``` + +this is equivalent to: + +```haskell +logDebug :: String -> Effect Unit +logDebug msg = do + menv <- Process.lookupEnv "NODE_ENV" + case menv of + Just env -> + if env == "DEVELOPMENT" then + Console.log msg + else + pure unit + Nothing -> pure unit +``` + +> [!info] +> Note that [guard](https://pursuit.purescript.org/packages/purescript-control/docs/Control.Alternative#v:guard) is a shorthand available for `when (..) empty` \ No newline at end of file diff --git a/fp/Class/Bind.md b/fp/Classes/Bind/Bind.md similarity index 100% rename from fp/Class/Bind.md rename to fp/Classes/Bind/Bind.md diff --git a/fp/Class/Monad.md b/fp/Classes/Bind/Monad.md similarity index 100% rename from fp/Class/Monad.md rename to fp/Classes/Bind/Monad.md diff --git a/fp/Class/Foldable.md b/fp/Classes/Foldable.md similarity index 100% rename from fp/Class/Foldable.md rename to fp/Classes/Foldable.md diff --git a/fp/Classes/Functor/Applicative.md b/fp/Classes/Functor/Applicative.md new file mode 100644 index 0000000..98c4b9c --- /dev/null +++ b/fp/Classes/Functor/Applicative.md @@ -0,0 +1,18 @@ +Adds the `pure` [[Functions|function]] to [[Apply]], allowing arbitrary values to be wrapped in a [[Functor]]. + +```haskell +class Apply f <= Applicative f where + pure :: forall a. a -> f a +``` + +### Examples +`pure a` in various types: + +type|equivalent to +---|--- +[[Array]]|`[a]` +[[List]]|`Cons a` +[[Maybe]]|`Just a` +[[Either]]|`Right a` +[[Effect]]|`() => a`more or less +[[Aff]]|`Promise.resolve(a)`more or less \ No newline at end of file diff --git a/fp/Classes/Functor/Apply.md b/fp/Classes/Functor/Apply.md new file mode 100644 index 0000000..b902b2b --- /dev/null +++ b/fp/Classes/Functor/Apply.md @@ -0,0 +1,79 @@ +Generalizes [[Functor#map|map]] to [[Functions|functions]] with 2+ arguments; lifting functions `a -> b -> c` to `f a -> f b -> f c` + +```haskell +class Functor f <= Apply f where + apply :: forall a b. f (a -> b) -> f a -> f b + +infixl apply as <*> +``` + +> [!tip] +> Apply often replaces the pattern of "building towards a final result" +> +> Consider a function that [[Tuple|tuple]]s together its arguments +> ```haskell +> mk3Tuple a b c = a /\ b /\ c +> ``` +> +> A common situation is wanting to build something like this 3-tuple from some components that are trapped in a context like [[Maybe]] or [[Either]], and we want to say "when all these things are ok, build it"; this is exactly what Apply lets us do: +> +> ```haskell +> maybeMk3Tuple :: Maybe a -> Maybe b -> Maybe c -> Maybe (a /\ b /\ c) +> maybeMk3Tuple ma mb mc = Just mk3Tuple <*> ma <*> mb <*> mc +> +> maybeMk3Tuple (Just 1) (Just 2) (Just 3) +> -- Just (1 /\ 2 /\ 3) +> +> maybeMk3Tuple (Just "a") (Just 3) (Nothing) +> -- Nothing +> +> maybeMk3Tuple Nothing Nothing Nothing +> -- Nothing +> ``` + +> [!tip] +> Obscure but occasionally usefully, Apply in collections lets us apply multiple functions to each element: +> ```haskell +> [(_ * 10), (_ * 20)] <*> [1, 2, 3] +> -- [10, 20, 20, 40, 30, 60] +> +> [identity, const ", "] <*> ["a", "b", "c"] +> -- ["a", ",", "b", ",", "c", ","] +> ``` + +### Examples + +lift `(a + b) / c` to [[Maybe]] +```haskell +f :: Number -> Number -> Number +f a b c = (a + b) / c + +mf :: Maybe Number -> Maybe Number -> Maybe Number +mf ma mb mc = pure f <*> ma <*> mb <*> mc +``` + +Build up a `Person` [[Record|record]] from Maybe fields; short-circuiting to `Nothing` if any fields are `Nothing` +```haskell +type PartialPerson = + { name :: Maybe String + , email :: Maybe String + , password :: Maybe String + } + +type Person = + { name :: String + , email :: String + , password :: String + } + +person :: PartialPerson -> Person +person + { name: name' + , email: email' + , password: password' + } = + let + buildPerson name email password = {name, email, password} + in + Just buildPerson <*> name' <*> email' <*> password' +``` \ No newline at end of file diff --git a/fp/Class/Functor.md b/fp/Classes/Functor/Functor.md similarity index 69% rename from fp/Class/Functor.md rename to fp/Classes/Functor/Functor.md index e777f08..b165dce 100644 --- a/fp/Class/Functor.md +++ b/fp/Classes/Functor/Functor.md @@ -1,4 +1,3 @@ -## What [[Typeclasses|Typeclass]] defining the [[Functions|function]] `map`, [[Infix Operators|operators]] `<$>`, and `<#>`. ```haskell @@ -6,11 +5,21 @@ class Functor f where map :: forall a b. (a -> b) -> f a -> f b ``` -## Why -Modify the data contained in a [[Data Structures|data structure]] +## map +For a [[Data Structures|data structure]] containing some data `a`, change the data using some function `a -> b`. -### Abstracts -- For every element in [[Collections|collection]] ... +> [!info] +> Another way of thinking of map is that it **lifts** a function of `a -> b` to `f a -> f b`: +> ```haskell +> addTwo :: Int -> Int +> addTwo = add 2 +> +> maybeAddTwo :: Maybe Int -> Maybe Int +> maybeAddTwo = map addTwo +> ``` + +Replaces the patterns: +- Modify every element in [[Collections|collection]] ... - When [[Maybe|nullable]] value is non-null ... - When _(potentially async)_ [[Effect|IO]] resolves ... diff --git a/fp/Class/Math/DivisionRing.md b/fp/Classes/Math/DivisionRing.md similarity index 100% rename from fp/Class/Math/DivisionRing.md rename to fp/Classes/Math/DivisionRing.md diff --git a/fp/Class/Math/EuclideanRing.md b/fp/Classes/Math/EuclideanRing.md similarity index 100% rename from fp/Class/Math/EuclideanRing.md rename to fp/Classes/Math/EuclideanRing.md diff --git a/fp/Class/Math/Ring.md b/fp/Classes/Math/Ring.md similarity index 100% rename from fp/Class/Math/Ring.md rename to fp/Classes/Math/Ring.md diff --git a/fp/Class/Math/Semiring.md b/fp/Classes/Math/Semiring.md similarity index 100% rename from fp/Class/Math/Semiring.md rename to fp/Classes/Math/Semiring.md diff --git a/fp/Class/Monoid.md b/fp/Classes/Monoid.md similarity index 100% rename from fp/Class/Monoid.md rename to fp/Classes/Monoid.md diff --git a/fp/Class/Semigroup.md b/fp/Classes/Semigroup.md similarity index 100% rename from fp/Class/Semigroup.md rename to fp/Classes/Semigroup.md diff --git a/fp/Class/Show.md b/fp/Classes/Show.md similarity index 100% rename from fp/Class/Show.md rename to fp/Classes/Show.md diff --git a/fp/Class/Alt.md b/fp/Classes/Traversable.md similarity index 100% rename from fp/Class/Alt.md rename to fp/Classes/Traversable.md diff --git a/fp/Class/Alternative.md b/fp/Data/Collections/NonEmptyArray.md similarity index 100% rename from fp/Class/Alternative.md rename to fp/Data/Collections/NonEmptyArray.md diff --git a/fp/Class/Applicative.md b/fp/Data/Collections/NonEmptyList.md similarity index 100% rename from fp/Class/Applicative.md rename to fp/Data/Collections/NonEmptyList.md diff --git a/fp/Class/Plus.md b/fp/Data/String.md similarity index 100% rename from fp/Class/Plus.md rename to fp/Data/String.md diff --git a/fp/Language/Infix Operators/Common Operators/Data.md b/fp/Language/Infix Operators/Common Operators/Data.md index 81a36b2..2bef78f 100644 --- a/fp/Language/Infix Operators/Common Operators/Data.md +++ b/fp/Language/Infix Operators/Common Operators/Data.md @@ -1,6 +1,7 @@ |Operator|Description|Associativity|Precedence|Defined As| |--|--|--|--|--| |`<>`|append|right|5|[`Data.Semigroup.append`](https://pursuit.purescript.org/packages/purescript-prelude/docs/Data.Semigroup#v:(%3C%3E))| +|`/\`|Tuple constructor|right|6|[`Data.Tuple.Nested.Tuple`](https://pursuit.purescript.org/packages/purescript-tuples/docs/Data.Tuple.Nested#v:(%2F%5C))| |`<$>`|map||| |`<#>`|flipped map||| |`<*>`|apply (map using function of 2+ arguments)||| diff --git a/fp/Monads/Transformers/ExceptT.md b/fp/Monads/Transformers/ExceptT.md new file mode 100644 index 0000000..e69de29 diff --git a/fp/Monads/Transformers/MaybeT.md b/fp/Monads/Transformers/MaybeT.md new file mode 100644 index 0000000..e69de29 diff --git a/fp/Monads/Transformers/ReaderT.md b/fp/Monads/Transformers/ReaderT.md new file mode 100644 index 0000000..e69de29 diff --git a/fp/Monads/Transformers/StateT.md b/fp/Monads/Transformers/StateT.md new file mode 100644 index 0000000..e69de29 diff --git a/fp/Monads/Transformers/WriterT.md b/fp/Monads/Transformers/WriterT.md new file mode 100644 index 0000000..e69de29