If you want to see how it works, see the README on the repo.
{-# LANGUAGE UndecidableInstances #-} | |
{-# LANGUAGE RankNTypes #-} | |
{-# LANGUAGE PolyKinds #-} | |
{-# LANGUAGE TypeOperators #-} | |
{-# LANGUAGE DataKinds #-} | |
{-# LANGUAGE TypeFamilies #-} | |
{-# LANGUAGE NoStarIsType #-} | |
{-# LANGUAGE GADTs #-} | |
module Pullbacks where |
Copyright © 2020, Philippe Bastiani.
with this restriction: this GIST could be, all or part, updated, copied, diffused for documentary purposes in the Λrrow project.
This GIST is an attempt to describe a repeatable, and automatable, process for building an embedded Domain Specific Language (DSL) with the help of a Free monad.
As material, i'll use Λrrow, the functional companion to Kotlin's Standard Library.
Disclaimer: This GIST assumes that you are roughly familiar with the concept of Free monad.
#!/usr/bin/env stack | |
{- stack --resolver lts-12.0 runghc -} | |
{-# LANGUAGE TypeFamilies, FlexibleInstances #-} | |
{-# LANGUAGE DataKinds, PolyKinds, KindSignatures, TypeInType #-} | |
{-# LANGUAGE AllowAmbiguousTypes, TypeApplications, GADTs #-} | |
import Prelude hiding ((.), id) | |
import qualified Prelude | |
import Data.Kind |
Add on top of default.nix: with import {};
or simply run as nix-build ''
(i. e. for nix-build complaining) or rather nix-build -E 'with import {}; callPackage ./default.nix {}'
(or even import)
I got interested in lenses because I was looking for a better way to handle state in front end applications (ELM Architecture and Redux were nice ideas but using Elm or PureScript face some management obstacles and Redux lacks types and more explicit composition). Studying them I found profunctors and the more I knew about them both the more interested I was. Now I look at optics as profunctor transformations that can be applied to a much wider menu of use cases than data accessors for nested structures.
This Gist is my collection of shortcuts to several resources here and there that either I consult frequently or I recommend frequently.
Optics as profunctor transformations are in correspondence with the profunctorial restrictions and have the following
// Providers | |
class Provider1 { } | |
protocol HasProvider1 { var provider1: Provider1 { get } } | |
class Provider2 { } | |
protocol HasProvider2 { var provider2: Provider2 { get } } | |
// a Provider that depends on the other two needs to be configured | |
protocol Configurable { | |
func configure(providerBag: HasProviders) |
There exist several DI frameworks / libraries
in the Scala
ecosystem. But the more functional code you write the more you'll realize there's no need to use any of them.
A few of the most claimed benefits are the following:
- Dependency Injection.
- Life cycle management.
- Dependency graph rewriting.
import java.util.function.Function; | |
import java.util.function.Consumer; | |
public class Cont<R, T> { | |
private final Function<Function<T, R>, R> cont; | |
public Cont(Function<Function<T, R>, R> k) { | |
cont = k; | |
} |
import Control.Monad.Reader | |
hello :: Reader String String | |
hello = do | |
name <- ask | |
return ("hello, " ++ name ++ "!") | |
bye :: Reader String String | |
bye = do | |
name <- ask |