All Projects → re-xyr → avail

re-xyr / avail

Licence: BSD-3-Clause License
Low-overhead effect management for concrete monads

Programming Languages

haskell
3896 projects

Labels

Projects that are alternatives of or similar to avail

FoundryVTT-Sequencer
This module implements a basic pipeline that can be used for managing the flow of a set of functions, effects, sounds, and macros.
Stars: ✭ 25 (-30.56%)
Mutual labels:  effects
RainbowTaskbar
Customizable Windows taskbar effects.
Stars: ✭ 39 (+8.33%)
Mutual labels:  effects
pedalboard
Online guitar pedalboard
Stars: ✭ 48 (+33.33%)
Mutual labels:  effects
limitless-engine
OpenGL C++ Graphics Engine
Stars: ✭ 95 (+163.89%)
Mutual labels:  effects
zio-http4s-example
For anyone who's struggling to put an http4s server together with ZIO
Stars: ✭ 19 (-47.22%)
Mutual labels:  effects
skyline
Some canvas experiments... like drawing a procedurally generated skyline. Also featuring fun explosions :D
Stars: ✭ 24 (-33.33%)
Mutual labels:  effects
pi-stomp
pi-stomp is a DIY high definition, multi-effects stompbox platform for guitar, bass and keyboards
Stars: ✭ 42 (+16.67%)
Mutual labels:  effects
JDSP4Linux
An audio effect processor for PipeWire and PulseAudio clients
Stars: ✭ 192 (+433.33%)
Mutual labels:  effects
vue-fake3d-image-effect
✨ A fake 3D Image Effect with WebGL - w/ VueJS - SSR Compatible
Stars: ✭ 15 (-58.33%)
Mutual labels:  effects
react-awesome-reveal
React components to add reveal animations using the Intersection Observer API and CSS Animations.
Stars: ✭ 564 (+1466.67%)
Mutual labels:  effects
shuffle-text
"shuffle-text" is JavaScript text effect library such as cool legacy of Flash.
Stars: ✭ 93 (+158.33%)
Mutual labels:  effects
Vuc
🎨 基于 Vuejs2 的 Canvas 组件库【服务器挂了。不在提供demo,github自带的静态网站不能发布,因为demo代码找不到了😂。】
Stars: ✭ 52 (+44.44%)
Mutual labels:  effects
ECardFlow
🍭A custom ViewPager for multiple card flow system. && A layout which provide beautiful background effects for ViewPager.
Stars: ✭ 47 (+30.56%)
Mutual labels:  effects
razer-cli
CLI for configuring Razer devices
Stars: ✭ 46 (+27.78%)
Mutual labels:  effects
SongProcessor
A beefed up version of AudioKit's Song Processor with the intention of releasing it on the App Store.
Stars: ✭ 36 (+0%)
Mutual labels:  effects
bow-openapi
🌐 Functional HTTP client generator from an OpenAPI/Swagger specification.
Stars: ✭ 47 (+30.56%)
Mutual labels:  effects
QQVoiceChange
Android NDK项目,继承 fmod音频引擎 实现仿QQ变声效果,可实现对录音进行变声,如 萝莉、大叔、搞怪、惊悚、空灵等效果,带领大家熟悉使用Android Studio+ CMake 集成 fmod 等C/C++框架的流程。
Stars: ✭ 26 (-27.78%)
Mutual labels:  effects
jquery-image-explode
A jQuery explosion plugin.
Stars: ✭ 57 (+58.33%)
Mutual labels:  effects
cleff
Fast and concise extensible effects
Stars: ✭ 66 (+83.33%)
Mutual labels:  effects
Amazing-Js-Projects
Amazing-Js-Projects
Stars: ✭ 99 (+175%)
Mutual labels:  effects

avail

avail is a companion to monad transformers that allows you to impose effect constraints on concrete monads. Specifically, instead of writing

myApp :: (MonadWriter Log m, MonadState Store m, MonadReader Env m) => m ()

it allows you to write

myApp :: Effs '[MonadWriter Log, MonadState Store, MonadReader Env] => App ()

where App is a specific, concrete monad stack.

Introduction

Current effects libraries all have one principle of effect restriction: an effect can be used in a monad if it can be interpreted in terms of the monad. This works well with a polymorphic monad type, but a polymorphic type is unfriendly to compiler optimization. In contrast, a concrete monad can be easily optimized, but if we fix a monad that supplies all the effects we need, we can no longer restrict what effects each function can use.

avail solves this problem with the phantom constraint pattern. We use a newtype wrapper M to screen out the user from directly manipulating the underlying monad, and performing any operation in a typeclass (for example, MonadIO) requires the corresponding phantom Eff constraint (in this case. Eff MonadIO) to be in scope. In other words, one can perform operations of a class only if:

  • The class is implemented for the monad, and
  • The effect constraint Eff e is available in the context.

The second requirement decouples the availability of effects from the monad implementation. At last, we use a function runM to clear the constraints and restore the underlying monad. A typical example looks like this:

import Avail
import Control.Monad.Reader
import Control.Monad.State

type App = M (ReaderT Int (State Bool))

testParity :: Effs '[MonadReader Int, MonadState Bool] => App ()
testParity = do
  num <- ask
  put (even num)

example :: IO ()
example = do
  print $ runM @'[MonadReader Int, MonadState Bool] testParity
    & (`runReaderT` 2)
    & (`execState` False)
  print $ runM @'[MonadReader Int, MonadState Bool] testParity
    & (`runReaderT` 3)
    & (`execState` False)

Through microbenchmarks and tests in some applications, the performance of using avail is at least on par with, and often better than, using the polymorphic counterparts.

Making avail work with new typeclasses

avail already comes with support of all mtl, exceptions, unliftio, monad-control and capability typeclasses. To add support for your own typeclass, for example:

class MonadOvO m where
  ...

You can use the Template Haskell utilities in the Avail.Derive module.

import Avail.Derive
avail [t| MonadOvO |]

There may be other more complicated cases, such as dependencies between classes and multi-param classes:

class (MonadOvO m, MonadQwQ m) => MonadUwU r m where
  ...

avail gets you covered:

import Avail.Derive
with1 \r -> avail'
  [ [t| MonadOvO |]
  , [t| MonadQwQ |]
  ] [t| MonadUwU $r |]

Limitations

  • Running effects: Because effect constraints in avail are detached from the monad structure, they cannot be run on a one-by-one basis. Practically, one can only run all effects and obtain the underlying concrete monad at once via runM. This means there is no exact equivalent to runReaderT, runExceptT etc on the M monad.

    If your application can entirely run on a single transformer stack (in particular, ReaderT IO, but also other transformer stacks), this is a non-issue because there will be no need to run effects one-by-one. For some other scenarios, there are some solutions that may be used solve this issue:

    • local is an almost identical substitute to runReaderT without destructing the monad.
    • Similarly, tryError is a substitute to runExceptT.
    • To simulate runStateT, simply set the value before the action and get the value after it.
    • listen is a very close analog to runWriterT.

Where is availability?

The old availability is abandoned due to its attempt at addressing two problems at once (capability and availability management), and may introduce confusion to new users on the choice between capability and availability. The new avail library focuses on availability management and acts not as a standalone effects library, but an alternative effect management layer that is used together with mtl or capability (which also reduces preformance overhead).

The old availability can be found at re-xyr/availability-old.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].