Git Product home page Git Product logo

purescript-free's Introduction

purescript-free

Latest release Build status Pursuit

Free monad, Cofree comonad, Yoneda and Coyoneda functors, and the Trampoline monad implementations for PureScript.

The Free monad implementation is represented using a sequential data structure.

See the following reference for further information.

Installation

spago install free

Documentation

Module documentation is published on Pursuit.

Benchmarks

The following benchmarks compare the implementation at v5.2.0 (commit f686f5fc07766f3ca9abc83b47b6ad3da326759a) with the implementation at v0.6.1 (commit 0df59c5d459fed983131856886fc3a4b43234f1f), which used the Gosub technique to defer monadic binds.

left-bind-small

left-bind-large

right-bind-small

right-bind-large

purescript-free's People

Contributors

ajnsit avatar ethul avatar garyb avatar jdegoes avatar jordanmartinez avatar kelden avatar kl0tl avatar liamgoodacre avatar maxdeviant avatar mikesol avatar milesfrain avatar mkaemmerer avatar natefaubion avatar paf31 avatar parsonsmatt avatar postsolar avatar puffnfresh avatar rintcius avatar safareli avatar telser avatar th-awake avatar thomashoneyman avatar vendethiel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

purescript-free's Issues

Use spago

Sorry if I'm totally out of my depth here when i suggest using spago for this project.

It would make it easier for people like me that are quite unexperienced with the purescript ecosystem to contribute to this project.

Currently my setup cant even run the tests properly using npm test, and i would guess it has something to do with this, since I generally don't have issues with the spago projects.

Merge with transformers

@ethul Would you be willing to merge your repo with transformers?

We'd like to use Trampoline to make various monads stack safe, but Free is also a transformer itself, so to avoid a circular dependency, I thought it might be best to try to merge the two.

What do you think?

Provide non memoized Trampoline?

Currently Trampoline is defined in terms of Lazy which is memoized. Because of this Trampoline is also memoized. But there could also exist non memoized definition for Trampoline using just ((->) Unit) (Currently -> is not MonadRec, but will become once purescript/purescript-tailrec#18 is merged). This implementation might be more efficient as it has no extra Lazy wrapper and memoization.

We have two options:

  1. use -> instead of Lazy in Trampoline
  2. define new Trampoline in terms of ->

take a look at how I fixed quadratic complexity of left associated chain without CatList

Hey folks,

I also had the issue of quadratic complexity on left associated chains on Free monad, and I fixed it by changing type of Free(Seq) this way:

data Seq f a where
    Pure :: a -> Seq f a
+  Lift :: f a -> Seq f a
-  Roll ::     f a -> (a -> Seq f b) -> Seq f b
+  Roll :: Seq f a -> (a -> Seq f b) -> Seq f b

And by placing Seq f a in Roll node instead of f a, I've avoided using CatList and chain is pretty simple as well:

Seq.prototype.chain = (f) => {
  // this way in Roll we don't have any `Pure` node
  if (Pure.is(this)) {
    return f(this.a)
  }
  return Roll(this, f)
} 

so when one associates chain to left Roll nodes are created/nested, and then on fold it could be inspected and interpreted safely.

I don't know Purescript that well, and can't suggest any way to implement Free this way, with lack of GADTs. but in case someone knows how it's possible, maybe implementation could become a bit simpler and straightforward.

this is the issue and fix commit

Broken bower redirect url

It looks like forking this repo for PR #19 has changed the redirect of the URL that is being used by bower. I was under the impression that if I forked and renamed the fork, github would still honor the existing redirect. However, I was wrong in this respect, and github now redirects from ethul/purescript-free to ethul/purescript-free-fork. I don't know if there is a way to set this straight on the github side of things.

As for bower, I requested to have the URL endpoint updated back in March. Nothing has changed though.

bower search purescript-free
purescript-free git://github.com/ethul/purescript-free.git

I might be able to unregister the bower package pointing to ethul/purescript-free and then reregister it pointing to purescript/purescript-free, but I wanted to give everyone a heads up on the problem and see if this is the best approach to resolve this issue.

Sorry about this.

Why is CatList Val and unsafeCoercion used instead of some type aligned sequence?

Today I finished reading of the referenced paper "Reflection without Remorse" (before I tried, but did not understood) and after that taking look at Free implementation made more sense but what I don't understand is why the CatList, Val and unsafeCoercion is used when some type aligned sequence could be used as in the paper?

Rearrange `unfoldCofree` arguments?

Currently we have:

unfoldCofree
  :: forall f s a
   . Functor f
  => s
  -> (s -> a)
  -> (s -> f s)
  -> Cofree f a

I think perhaps this would seem more natural, given the kind of argument order we usually use:

unfoldCofree
  :: forall f s a
   . Functor f
  => (s -> a)
  -> (s -> f s)
  -> s
  -> Cofree f a

Bug: Interpreters become one-time-use when called from js

This is a strange one, so I've set up a repo that reproduces the issue:

https://github.com/MichaelXavier/purescript-free-bug

I've got a stripped down version of the example that uses the coyoneda free and goEffC. The issue is that if you call effectful code that runs the interpreter multiple times from JS, it only gets run once. I suspect this may be a bug in goEffC. I don't know if this extends to the other free patterns. I've noted in the readme that if you construct a new interpreter at every use (e.g. i <- return myInterpreter), the code behaves as expected.

push more cofree operations through the trampoline

Right now only a few operations (such as <$>) are pushed through the trampoline, the remainder are executed on the stack which will mean the cofree data structures must be small enough to process recursively.

Error in running the examples.

HI,

I get an error:

Error in declaration main
No instance found for Prelude.Show (Control.Monad.Eff.Eff (trace :: Debug.Trace.Trace) Prelude.Unit)

when i try to run the examples in the psci. Is there some setup I need to make to get it running in the interactive mode? Things compile and load fine and fail when the main is called. Thanks for your help.

Add role annotation to `Free`

data Free f a = Free (FreeView f Val Val) (CatList (ExpF f))

a is never used in the implementation of Free so it gets inferred as phantom which causes problems when using coerce.

Move to core

@ethul would you mind if we moved this to the main purescript org? It's not that we want to take it off your hands, just that it's extremely useful and would fit well as one of the core libraries.

Left-associated binds causing `RangeError: Maximum call stack size exceeded`

Right-associated binds are working fine, but in the case of left-associated binds, the call stack size is being exceeded. Below is an example illustrating the issue.

module Main where

import Control.Monad.Eff
import Control.Monad.Trampoline

import Data.Array (range)
import Data.Foldable (foldl)

import Debug.Trace (Trace(), trace)

-- Derived from https://github.com/mandubian/cats/tree/feature/freer

gen :: forall a. a -> Trampoline a
gen = suspend <<< done

leftBind :: forall f. Number -> Trampoline Number
leftBind n = foldl (\b a -> b >>= const (gen a)) (gen 0) (range 1 n)

foreign import now "function now(){ return new Date().valueOf(); }" :: forall eff. Eff eff Number

runner :: forall eff. Number -> Eff (trace :: Trace | eff) Unit
runner n = do
  t1 <- now
  pure $ runTrampoline $ leftBind n
  t2 <- now

  trace $ "leftBind: " ++ show (t2 - t1)

  return unit

main = do
  runner 100
  runner 500
  runner 1000
  runner 5000
  runner 10000

Running this produces.

$ node psc
leftBind: 6
leftBind: 11
leftBind: 20
leftBind: 95

/purescript-free-perf2/psc.js:8651
                        return _383.value0(function (a) {
                                                    ^
RangeError: Maximum call stack size exceeded

composition of cofree comonads

I worked out a way to compose cofree comonads:
http://try.purescript.org/?gist=b31f48d16ad43cec8c0afcd470ac5add

there is the function:

compose
  :: forall f g a b
   . Functor f
  => Functor g
  => Cofree f a
  -> Cofree g b
  -> Cofree (Product f g) (Tuple a b)
compose f g =
  mkCofree
    (Tuple (head f) (head g))
    (fn (tail f) (tail g))
  where
    fn :: f (Cofree f a) -> g (Cofree g b) -> Product f g (Cofree (Product f g) (Tuple a b))
    fn fa gb = uncurry compose <$> (product (flip Tuple g <$> fa) (Tuple f <$> gb))

Is there a place for it in the Control.Comonad.Cofree module?

Expose `Cofree` constructor

Currently there's no way to make a single lazy Cofree node since the constructor is not exported, and mkCofree is strict.

Free Applicative

I'd like to implement the Free Applicative. Do we want it in this library, or should I start a new one?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.