commit 338ae34f00f8a17190cfb4a2cacdabede67a3a54
Author: Matei Adriel <rafaeladriel11@gmail.com>
Date:   Thu Apr 1 19:33:36 2021 +0300

    feat(abilities): Io & Ask abilities

diff --git a/abilities/.gitignore b/abilities/.gitignore
new file mode 100644
index 0000000..30efe19
--- /dev/null
+++ b/abilities/.gitignore
@@ -0,0 +1,10 @@
+/bower_components/
+/node_modules/
+/.pulp-cache/
+/output/
+/generated-docs/
+/.psc-package/
+/.psc*
+/.purs*
+/.psa*
+/.spago
diff --git a/abilities/a.txt b/abilities/a.txt
new file mode 100644
index 0000000..184d3d7
--- /dev/null
+++ b/abilities/a.txt
@@ -0,0 +1 @@
+hello from a!
\ No newline at end of file
diff --git a/abilities/b.txt b/abilities/b.txt
new file mode 100644
index 0000000..850b0b2
--- /dev/null
+++ b/abilities/b.txt
@@ -0,0 +1 @@
+hello from b!
\ No newline at end of file
diff --git a/abilities/packages.dhall b/abilities/packages.dhall
new file mode 100644
index 0000000..644dfff
--- /dev/null
+++ b/abilities/packages.dhall
@@ -0,0 +1,110 @@
+{-
+Welcome to your new Dhall package-set!
+
+Below are instructions for how to edit this file for most use
+cases, so that you don't need to know Dhall to use it.
+
+## Warning: Don't Move This Top-Level Comment!
+
+Due to how `dhall format` currently works, this comment's
+instructions cannot appear near corresponding sections below
+because `dhall format` will delete the comment. However,
+it will not delete a top-level comment like this one.
+
+## Use Cases
+
+Most will want to do one or both of these options:
+1. Override/Patch a package's dependency
+2. Add a package not already in the default package set
+
+This file will continue to work whether you use one or both options.
+Instructions for each option are explained below.
+
+### Overriding/Patching a package
+
+Purpose:
+- Change a package's dependency to a newer/older release than the
+    default package set's release
+- Use your own modified version of some dependency that may
+    include new API, changed API, removed API by
+    using your custom git repo of the library rather than
+    the package set's repo
+
+Syntax:
+where `entityName` is one of the following:
+- dependencies
+- repo
+- version
+-------------------------------
+let upstream = --
+in  upstream
+  with packageName.entityName = "new value"
+-------------------------------
+
+Example:
+-------------------------------
+let upstream = --
+in  upstream
+  with halogen.version = "master"
+  with halogen.repo = "https://example.com/path/to/git/repo.git"
+
+  with halogen-vdom.version = "v4.0.0"
+-------------------------------
+
+### Additions
+
+Purpose:
+- Add packages that aren't already included in the default package set
+
+Syntax:
+where `<version>` is:
+- a tag (i.e. "v4.0.0")
+- a branch (i.e. "master")
+- commit hash (i.e. "701f3e44aafb1a6459281714858fadf2c4c2a977")
+-------------------------------
+let upstream = --
+in  upstream
+  with new-package-name =
+    { dependencies =
+       [ "dependency1"
+       , "dependency2"
+       ]
+    , repo =
+       "https://example.com/path/to/git/repo.git"
+    , version =
+        "<version>"
+    }
+-------------------------------
+
+Example:
+-------------------------------
+let upstream = --
+in  upstream
+  with benchotron =
+      { dependencies =
+          [ "arrays"
+          , "exists"
+          , "profunctor"
+          , "strings"
+          , "quickcheck"
+          , "lcg"
+          , "transformers"
+          , "foldable-traversable"
+          , "exceptions"
+          , "node-fs"
+          , "node-buffer"
+          , "node-readline"
+          , "datetime"
+          , "now"
+          ]
+      , repo =
+          "https://github.com/hdgarrood/purescript-benchotron.git"
+      , version =
+          "v7.0.0"
+      }
+-------------------------------
+-}
+let upstream =
+      https://github.com/purescript/package-sets/releases/download/psc-0.14.0-20210318/packages.dhall sha256:98bbacd65191cef354ecbafa1610be13e183ee130491ab9c0ef6e3d606f781b5
+
+in  upstream
diff --git a/abilities/spago.dhall b/abilities/spago.dhall
new file mode 100644
index 0000000..c3fec45
--- /dev/null
+++ b/abilities/spago.dhall
@@ -0,0 +1,17 @@
+{-
+Welcome to a Spago project!
+You can edit this file as you like.
+-}
+{ name = "my-project"
+, dependencies =
+  [ "assert"
+  , "console"
+  , "debug"
+  , "effect"
+  , "node-fs"
+  , "psci-support"
+  , "unsafe-coerce"
+  ]
+, packages = ./packages.dhall
+, sources = [ "src/**/*.purs", "test/**/*.purs" ]
+}
diff --git a/abilities/src/Abilities.purs b/abilities/src/Abilities.purs
new file mode 100644
index 0000000..b183a97
--- /dev/null
+++ b/abilities/src/Abilities.purs
@@ -0,0 +1,9 @@
+module Abilities where
+
+import Prelude hiding (bind, discard)
+
+bind :: forall a b. a -> (a -> b) -> b
+bind = (#)
+
+discard :: forall a b. a -> (a -> b) -> b
+discard = bind
\ No newline at end of file
diff --git a/abilities/src/Ask.js b/abilities/src/Ask.js
new file mode 100644
index 0000000..c192f69
--- /dev/null
+++ b/abilities/src/Ask.js
@@ -0,0 +1 @@
+exports.ask = (dict) => dict.ctx;
diff --git a/abilities/src/Ask.purs b/abilities/src/Ask.purs
new file mode 100644
index 0000000..66feb69
--- /dev/null
+++ b/abilities/src/Ask.purs
@@ -0,0 +1,16 @@
+module Ask where
+
+import Prelude hiding (bind,discard)
+
+import Unsafe.Coerce (unsafeCoerce)
+
+class Ask a where
+    ctx :: a
+
+pure :: forall ctx a. a -> Ask ctx => a
+pure a = a
+
+foreign import ask :: forall ctx. ((Ask ctx) => ctx)
+
+handleAsk :: forall a ctx. ctx -> (Ask ctx => a) -> a
+handleAsk = unsafeCoerce \c f -> f { ctx: c }
diff --git a/abilities/src/Io.purs b/abilities/src/Io.purs
new file mode 100644
index 0000000..aabaaf8
--- /dev/null
+++ b/abilities/src/Io.purs
@@ -0,0 +1,30 @@
+module Io where
+
+import Prelude hiding (bind,discard)
+
+import Effect (Effect)
+import Effect.Class.Console as Console
+import Node.Encoding (Encoding(..))
+import Node.FS.Sync as Fs
+import Test.Assert as Assert
+import Unsafe.Coerce (unsafeCoerce)
+
+class Io
+
+pure :: forall a. a -> Io => a
+pure a = a
+
+assert :: Boolean -> (Io => Unit)
+assert = Assert.assert >>> effectToIo
+
+handleIo :: forall a. (Io => a) -> Effect a
+handleIo = unsafeCoerce
+
+effectToIo :: forall a. Effect a -> (Io => a)
+effectToIo = unsafeCoerce
+
+debugLog :: String -> Io => Unit
+debugLog = Console.log >>> effectToIo
+
+readFile :: String -> Io => String
+readFile = Fs.readTextFile UTF8 >>> effectToIo 
diff --git a/abilities/src/Main.purs b/abilities/src/Main.purs
new file mode 100644
index 0000000..8f02fa3
--- /dev/null
+++ b/abilities/src/Main.purs
@@ -0,0 +1,32 @@
+module Main where
+
+import Prelude
+
+import Ask (class Ask, handleAsk)
+import Ask as Ask
+import Effect (Effect)
+import Effect.Console (logShow)
+import Io (class Io, handleIo)
+import Io as Io
+import Abilities as Abilities
+
+something :: Ask Int => Io => Int
+something = Abilities.do
+  let a = 3
+
+  Io.assert $ a + 1 == 4
+  Io.debugLog $ show a
+
+  -- Let works just as well
+  b <- Io.readFile "b.txt"
+
+  Io.debugLog $ Io.readFile "a.txt" <> "!!"
+  Io.debugLog b
+
+  a + Ask.ask * 2
+
+main :: Effect Unit
+main = do
+  result <- handleAsk 3 $ handleIo something
+  result' <- handleAsk 5 $ handleIo something
+  logShow [result, result']
diff --git a/abilities/test/Main.purs b/abilities/test/Main.purs
new file mode 100644
index 0000000..f91f98c
--- /dev/null
+++ b/abilities/test/Main.purs
@@ -0,0 +1,11 @@
+module Test.Main where
+
+import Prelude
+
+import Effect (Effect)
+import Effect.Class.Console (log)
+
+main :: Effect Unit
+main = do
+  log "🍝"
+  log "You should add some tests."