Effects in Idris: how to create them and a use for them to force proofs

  • Pre-application of our monad; there are no matching items in the rows. If no other effects are being used, the left hand list of EFFECT equals []. In any case, an EFFECT for the Effect we’re interested in hasn’t been introduced yet. One can think of “Eff () []” as the expected Effect state.
  • Running of our monad; an EFFECT exists in the Eff monad’s EFFECT list that is compatible with our Effect. One can think of “Eff () [OUREFFECT Initialized]” as the expected Effect state if Initialized is the state we want to start OUREFFECT in. I’ll talk about effect states a bit later.
  • Finish of our monad; an EFFECT exists in the expected end state in the Eff monad’s EFFECT list and it is provably compatible with the expected end state. This proves that we have satisfied conditions for the monad’s use.
  • 0: An ordinary datum in ADT or record form that contains actual PoD information regarding the state the effect has been left in. It is modified in a way that I’ll explain in a bit.
  • 1: A GADT Type wrapper for the above data.
  • 2: An Effect ADT with elements whose type is built by the ‘sig’ function in idris’ effects package. sig takes 3 or 4 arguments and I’ll try to explain what it’s doing in a bit. Just note that the cases in this ADT represent the actions that can be taken in this Effect (everything you can order it to do) and contain expected precondition states and expected postcondition states for the Effect in terms of Types.
  • 3: A GADT yielding EFFECT which is basically the same as PROCESS, CONSOLE, EXCEPTION, AFF, SIGNAL etc in purescript. It is constructed by MkEff from Effects and given a datum of our effect’s content type (0 above) combines it with the type wrapper (1 above) and the effect methods (2 above). This is the name we’ll use everywhere else to refer to our effect in the code.
  • 4: A Handler implementation for (2) that carries out actual actions in a more primitive monad, such as IO. These could be FFI functions that do mutations outside idris, ST actions that modify state data or even empty actions on the universe that serve only to change the Type of the effect state.
  • 5: A Default implementation for the Type that is taken on by (2) that the EFFECT starts life in. When a do block requiring one of these as a precondition is encountered and there is no active EFFECT (4) in the list maintained by Eff for the preconditions of the environment surrounding the block, the “default” method of the “Default” instance will yield a Type to be inserted into the preconditions automatically.
  • 6: End user accessible functions which invoke “call” on one of the data constructors in (2).
doTryAssert : Eff () [ASSERTION NotFailed] [ASSERTION NotFailed]
doTryAssert =
do
let x = True -- Not well typed if x is False
assert x (trueEqualsTrue x)
let y = 2 /= 3 -- Not well typed for 3 /= 3
assert y (twoIsLessThanThree)
runAssertions : Eff () [ASSERTION NotFailed]
runAssertions = do
doTryAssert
main : IO ()
main = run runAssertions
data AssertionState = NotFailed | Failed
data AssertionInfo : AssertionState -> Type where
DI : AssertionInfo s
data AssertionEff : Effect where
FailAssertion :
sig AssertionEff ()
(AssertionInfo NotFailed)
(AssertionInfo Failed)
OkAssertion :
sig AssertionEff ()
(AssertionInfo NotFailed)
(AssertionInfo NotFailed)
ASSERTION : AssertionState -> EFFECT
ASSERTION t = MkEff (AssertionInfo t) AssertionEff
implementation Handler AssertionEff IO where
handle res FailAssertion k = do
putStrLn "Assertion failed"
k () DI
handle res OkAssertion k = do
k () DI
implementation Default (AssertionInfo NotFailed) where
default = DI
assert : (x : Bool) -> (prf : (x = True)) -> Eff () [ASSERTION NotFailed] [ASSERTION (if x then NotFailed else Failed)]
assert False _ = call FailAssertion
assert True Refl = call OkAssertion

An old programmer learning new tricks.

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Array Methods

8 Reasons ReactJS is Perfect for Web-based Apps

ReactJs

Stop looking hard into graphql — Sails/Waterline solves it all

Customise your classes with decorators

Writing a Web Socket Server with Embedded Jetty

Lesson 4: components @viewchild reference

The magic of RawRepresentable in Swift

“Copy Value” for Wallaby and Quokka

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
art yerkes

art yerkes

An old programmer learning new tricks.

More from Medium

ESP-IDF Logging: How great is ‘ESP_LOGx’ vs ‘printf’

ESP-IDF Logging: sample logs using ESP_LOG screenshot

How PVS-Studio prevents rash code changes, example N3

You typed gcc main.c — What just happened?

Integrating Lua with C: Part 4