Code Monkey home page Code Monkey logo

freer-simple's People

Contributors

adaszko avatar andremarianiello avatar elvishjerricco avatar fosskers avatar hurryabit avatar isovector avatar justusadam avatar lazersmoke avatar lexi-lambda avatar liskin avatar lysxia avatar mdimjasevic avatar pseudonom avatar queertypes avatar schell avatar sorki avatar tehnix avatar tmcgilchrist avatar trskop avatar xkollar 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

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

freer-simple's Issues

Suggestion to improve type inference

I really want to like freer-simple, but I can't until it infers at least as well as idiomatic mtl usage. The big problem at the moment is Member:

class FindElem eff effs => Member (eff :: * -> *) effs

This multi-parameter type class infers miserably because there is no connection between the parameters. However, we can do better! Ignoring FindElem for now, this has much better inference, at the cost of: a. limiting you to a single type of effect and b. Adding a parameter to effect definitions:

class Member ( eff :: k -> * -> * ) config effs | effs eff -> config

That is, if I know the set of effects and a particular effect, I can tell you the "configuration" of that effect. Configured or parameterized effects are polymorphic effects such Reader, State, etc. This encoding means

Member Reader r effs

is like

MonadReader r m

This has the same "drawbacks" as functional dependencies in mtl, but I believe those drawbacks are significantly overblown. The good news is that as effects are first class in freer-simple, it's pretty trivial to just newtype Reader for example to have it occur twice (at different types) in eff.

The complication to the kind of eff can probably be worked around with

data Mono (eff :: * -> *) (config :: ()) a where
  Mono :: eff a -> Mono '() a

or something.

What do you think? Happy to throw up a PR if you want to see how it looks in practice. I'm using this in a private extensible effects like library to much success.

interpretM sometimes needs extra constraints

So compositions of interpretM seem to have trouble carrying through LastMember constraints, somehow. This is the smallest example I could construct that reproduces.

Removing the marked line works around the problem.

{-# LANGUAGE RankNTypes, TypeOperators, GADTs, DataKinds, FlexibleContexts #-}

module Main where

import Control.Monad.Freer

data Fx1 a where
  Fx1 :: Fx1 ()

data Fx2 a where
  Fx2 :: Fx2 ()

runFx :: forall effs a
      .  ( LastMember IO effs
         , LastMember IO (Fx1 ': effs) -- COMMENT OUT TO FIX
         )
      => Eff (Fx2 ': Fx1 ': effs) a
      -> Eff effs a
runFx
  = interpretM (\Fx1 -> putStrLn "Fx1")
  . interpretM (\Fx2 -> putStrLn "Fx2")

main :: IO ()
main = runM . runFx $ do
  send Fx1
  send Fx2
src/Main.hs:21:5: error:
    • Could not deduce (Monad (Data.OpenUnion.Last (Fx1 : effs)))
        arising from a use of ‘interpretM’
      from the context: LastMember IO effs
        bound by the type signature for:
                   runFx :: forall (effs :: [* -> *]) a.
                            LastMember IO effs =>
                            Eff (Fx2 : Fx1 : effs) a -> Eff effs a
        at src/Main.hs:(13,1)-(18,19)
      There are instances for similar types:
        instance Monad Data.Semigroup.Last -- Defined in ‘Data.Semigroup’
    • In the second argument of ‘(.)’, namely
        ‘interpretM (\ Fx2 -> putStrLn "Fx2")’
      In the expression:
        interpretM (\ Fx1 -> putStrLn "Fx1")
          . interpretM (\ Fx2 -> putStrLn "Fx2")
      In an equation for ‘runFx’:
          runFx
            = interpretM (\ Fx1 -> putStrLn "Fx1")
                . interpretM (\ Fx2 -> putStrLn "Fx2")
   |
21 |   . interpretM (\Fx2 -> putStrLn "Fx2")
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

src/Main.hs:21:25: error:
    • Could not deduce: Data.OpenUnion.Last (Fx1 : effs) ~ IO
      from the context: LastMember IO effs
        bound by the type signature for:
                   runFx :: forall (effs :: [* -> *]) a.
                            LastMember IO effs =>
                            Eff (Fx2 : Fx1 : effs) a -> Eff effs a
        at src/Main.hs:(13,1)-(18,19)
      or from: x ~ ()
        bound by a pattern with constructor: Fx2 :: Fx2 (),
                 in a lambda abstraction
        at src/Main.hs:21:18-20
      Expected type: Data.OpenUnion.Last (Fx1 : effs) x
        Actual type: IO ()
    • In the expression: putStrLn "Fx2"
      In the first argument of ‘interpretM’, namely
        ‘(\ Fx2 -> putStrLn "Fx2")’
      In the second argument of ‘(.)’, namely
        ‘interpretM (\ Fx2 -> putStrLn "Fx2")’
    • Relevant bindings include
        runFx :: Eff (Fx2 : Fx1 : effs) a -> Eff effs a
          (bound at src/Main.hs:19:1)
   |
21 |   . interpretM (\Fx2 -> putStrLn "Fx2")
   |

Provide instances for MTL interop

Some libraries, like lens, provide functions that are meant for use in MTL transformer stacks. Example:

http://hackage.haskell.org/package/lens-4.17/docs/Control-Lens-Setter.html#g:5

If Eff had an instance for MonadState, then I could use those Lens functions without having to rewrite them using the put and get from Control.Monad.Freer.State - it would happen automatically.

I have spent a number of days on this, but my instance manipulation skills are not the greatest, so I ended up with something like this:

instance MTL.MonadState s (Eff (State s ': effs)) where
get = get
put = put

instance {-# OVERLAPPABLE #-} MTL.MonadState s (Eff effs) => MTL.MonadState s (Eff (eff ': effs)) where
get = MTL.get
put = MTL.put

-- single actions that uses MTL and Eff values together without wrapping/unwrapping newtypes
action :: Eff (State Bool ': effs) ()
action = do
b <- MTL.get
put $ not b

ranAction :: Eff effs ((), Bool)
ranAction = runState True action

I also tried a solution involves defining an instance for a newtype wrapping Eff and using the constraints library to unsafely deduce MonadState s (Eff effs) from Member (State s) effs, but I had to use explicit TypeApplication to get it to work. I can post the code for that if you think that avenue is more likely where you would want to go with this.

A third possibility would be using something from the reflection package to provide the instance at runtime, but I haven't explored that.

I have only been playing around with

TL;DR: I don't know the best way to do this, but I think this library can provide something helpful for this use case.

How are you meant to use `interpose`?

The way I thought interpose was meant to be used was to respond to events without actually handling them – I imagined this was maybe for cross cutting concerns like tracing. But surprisingly interpose requires a naturall transformation eff ~> Eff effs, meaning I have to "respond" with the correct type with the handler I give to interpose which doesn't make a lot of sense to me with my imagination. What also seems strange to me is that apparently interpose and interposeWith require me to produce a response... so how is that not handling the effect?

So, what am I missing here? What is interpose actually meant to be used for?

To put it in code, I'd have expected interpose to be more like

Member eff effs => (forall v. eff v -> (v -> Eff effs v)) -> Eff effs ~> Eff effs

I.e. we get a look at the incoming "request" and the outgoing "response" but we're not responsible for actually producing the response.


NVM. What I missed was that you can still use the effect you're interposing within interpose itself, so you can do what I just described with

interposeLikeIThought :: Member eff effs => (forall v. eff v -> (v -> Eff effs v)) -> Eff effs ~> Eff effs
interposeLikeIThought f = interpose $ \req -> do
  send req >>= f req

MonadBaseControl instances

I was looking at trying to use resource-pool in an Eff stack and ran into an issue where I could not get a MonadBaseControl instance for an eff stack. This makes sense to me as there are none defined. Is it possible to define them, and if so would this library be interested in accepting a PR that adds it?

`raise` an arbitrary number of times

Apologies if there is a basic resolution to the issue.

Is there a way to call one action inside another, if the called action has only a subset of the caller's effects? For example, something with type foo :: (Members subset superset) => Eff subset () -> Eff superset ().

The following fails to compile, since (obviously) subset ~ superset is not true:

foo :: (Members subset superset) => Eff subset () -> Eff superset ()
foo = id
-- Could not deduce: subset ~ superset from the context...

and the following also doesn't typecheck because AFAICT raise is too concrete, requiring something of the form eff ': subset:

foo :: (Members subset superset) => Eff subset () -> Eff superset ()
foo = raise . id
-- Could not deduce: superset ~ (e0 : subset) from the context...

If worse comes to worse, I can make all my types concrete and use raise as many times as necessary, but I'm hoping there's a solution that doesn't require such premature specialization.

(Thanks for your work on freer-simple, it's a wonderful library!)

EDIT: Fixed a typo in the second code example.

First Example in API Docs Looks Wrong

runInMemoryFileSystem includes the following:

WriteFile path contents -> modify $ \vfs ->
      (path, contents) : delete (path, contents) vfs

This seems a bit strange if it is meant to simulate a file system because the old "file" would only get deleted if the path and the contents were the same. Overwriting a path with different contents would result in 2 files in memory with different contents and the same path.

I think the data structure needs to be changed to a Map or the WriteFile case changed to something like:

WriteFile path contents -> modify $
       \vfs -> (path, contents) : deleteBy (\t0 t1 -> fst t0 == fst t1) (path, contents) vfs

Trouble using makeEffect on a GADT with nested variables in the type constructor

I ran into an issue when running a program like this

{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE FlexibleContexts #-}
module Main where

import Control.Monad.Freer.TH

main :: IO ()
main = return ()

data Test a where
  Test :: forall b. Maybe b -> Test ()

makeEffect ''Test

The error was:

    /root/tmp/app/Main.hs:16:1: error:
        The exact Name ‘b_XC7’ is not in scope
          Probable cause: you used a unique Template Haskell name (NameU),
          perhaps via newName, but did not bind it
          If that's it, then -ddump-splices might be useful
       |
    16 | makeEffect ''Test
       | ^^^^^^^^^^^^^^^^^

and the splices were

app/Main.hs:16:1-17: Splicing declarations
    makeEffect ''Test
  ======>
    test ::
      forall effs_a46Q.
      Data.OpenUnion.Internal.Member Test effs_a46Q =>
      Maybe b_XC7 -> Control.Monad.Freer.Internal.Eff effs_a46Q ()
    test a_a46R = Control.Monad.Freer.Internal.send (Test a_a46R)

It seems like makeEffect tries to determine what variables to stick in the context of the generated function by pulling our top-level type variables (i.e. VarT) from the constructor, but Maybe b is not a VarT so it gets missed.

Inserting effects underneath others

I find myself wanting to have values with a very specific list of effects, to constrain what my users can do, e.g. Eff '[E1, E2] a.

However, I then have issues interpreting those: if E1 can be interpreted in terms of E3, I need to get E3 under E1 (and perhaps E2) in the stack.

But this seems hard to do. I've managed to write:
raiseBehind :: forall effs a . Eff '[a] ~> Eff (a ': effs)
but I can't figure out how to write
raiseBehindMany :: forall effs effs' . Eff effs ~> Eff (effs :++: effs')
although it seems like it should be sensical.

For the time being, I'm working around this by using
data SomeEffs effs a = SomeEffs { runSomeEffs :: forall effs' . Members effs effs' => Eff effs' a }
but this isn't very nice.

Is it possible to define 'mapWriter' for the Writer effect?

I have an effect stack with a Writer () in it someplace. I want to keep the stack the same, but instead of having Writer () in that place, I want Writer w for some suitable w. If I was using MTL, I would use mapWriter to achieve this, but there seems to be no analog for it here.

Is this possible to define somehow, and if so, how would I do it?

Documentation about composing IO effects

IMO one common use case for this library is to have an algebra of effects over some IO actions. You never end up with only one effect using IO. For example you may need to wrap file handling in an effect and also spawning external processes. I couldn't find out how to compose the interpretation of these in any of the docs and since this is a new library there are few other resources. In the end I was able to compose interpretM functions for each however it required quit a few type annotations to get it to work. Something like this:

-- this is in my Main module

interpretIO ::
     (LastMember IO effs, Members '[ IO] effs)
  => Eff (Console ': File ': Process ': Error AppError ': effs) a
  -> Eff effs (Either AppError a)
interpretIO =
  runError . Process.interpretIO . File.interpretIO . Console.interpretIO

runApp :: Spec -> IO ()
runApp spec = do
  eRes <- runM . interpretIO . runSpec $ spec
  case eRes of
    Left (ProcessFailed ec) -> exitWith $ ExitFailure ec
    Right res          -> pure ()

Where File.interpretIO is:

interpretIO ::
     (LastMember IO effs, Members '[ IO] effs)
  => Eff (File ': effs) a
  -> Eff effs a
interpretIO =
  interpretM
    (\case
       WriteFile path text -> Text.writeFile path text
       ReadFile path -> tryReadFile path
       CreateDirectoryIfMissing parents path ->
         Dir.createDirectoryIfMissing parents path
       GetHomeDirectory -> Dir.getHomeDirectory
       GetCurrentDirectory -> Dir.getCurrentDirectory)

As an example of the type inference problem, I was forced to create interpretIO in Main since eRes <- runM . runError . Process.interpretIO . File.interpretIO . Console.interpretIO . runSpec $ spec would not type check, there were issues with constraints.

Of course I may be doing this completely the wrong way but I need some help from the documentation on this :-)

How do you do something like `reinterpret2`, but backwards?

I'm looking for a way to say that if the next two effects are f and g, then replace them with h.

A type something like: forall f g h effs. (f ': g ~> Eff (h ': effs)) -> Eff (f ': g ': effs) ~> Eff (h ': effs)

Is there is an easy way of doing this which I am missing? If not, would someone be willing to help me implement it and generate a pull request for it?

How to use `reinterpret2` without hardcoding effect order.

I'm having an issue using reinterpret2. I have a database effect that looks something like this:

data Database r where
    GetUser :: UUID -> Database (Maybe User)

Interpreting this into IO is all pretty straightforward, but I want to interpret it into IO plus an Error effect. I guess what I want is something like the following:

runDatabase :: (Members '[IO, (Error DatabaseError)] effs') => Connection -> Eff (Database ': effs) a -> Eff effs' a

But because the return value of reinterpret2 hardcodes the efffect order I can't figure out how to do this.

Of course I might just be using reinterpret2 in an entirely inappropriate way so any advice welcome :).

Problem with introducing new intermediate states

Something that I used to do a lot of with free-effects was this:

{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE PackageImports #-}

module Bug where

import "freer-simple" Control.Monad.Freer
import "freer-simple" Control.Monad.Freer.State

foo :: Member IO r => Eff r Int
foo = execState 0 $ do
    put 10

{-
• Could not deduce (freer-simple-1.0.0.0:Data.OpenUnion.Internal.FindElem
                      (State Integer) r (State Int : r))
    arising from a use of ‘put’
  from the context: Member IO r
    bound by the type signature for:
               foo :: forall (r :: [* -> *]). Member IO r => Eff r Int
    at /Users/johnw/dl/Bug.hs:9:1-31
• In a stmt of a 'do' block: put 10
  In the second argument of ‘($)’, namely ‘do put 10’
  In the expression: execState 0 $ do put 10
-}

However, with freer-simple this same code gives me type errors that I've yet to work around. Surely I'm just missing something obvious?

Simpler example of pure interpreter

There's a lot going on in runConsolePure. Although it could be educational, I think you have to understand a fair bit more to know what's going on.

Can you please provide an example of a "pure" interpreter that doesn't involve any other effects? One that's just a function?

Support for template-haskell 2.19?

The latest GHC versions use template-haskell-2.19.0.0, but this package is incompatible.

Unfortunately all GHC versions before 9.4.2 cause segfaults on my machine, otherwise I would just downgrade.

Section on related libraries / resources etc in the readme

There are now related libraries such as freer-simple-time and a number of blogs et.al etc. floating around in the hackage / the googlesphere.

Would a relate links section under acknowledgements in the readme (including a disclaimer) be useful?

Happy to provide PR if you think it is.

Lifting IO effect to ResourceT

I have a bunch of interpreters which are described with Member IO r constraint.

I also have one effect whose interpreter needs to take care of resources so it wants Member (ResourceT IO) r. This comes from 3rd party libraries, in my case amazonka, so I can't really get rid of ResourceT here.

What would be the best way to compose these effects? Or is there a way to somehow "lift" existing IO effects into ResourceT IO when composing interpreters?

Release a version compatible with template-haskell-2.15

Kindly do a hackage revision, or release a new version that allows for template-haskell-2.15.

It is currently constrained to template-haskell < 2.15, but it seems to work fine.

I was able to reproduce a successful build & test locally like so:

stack unpack freer-simple-1.2.1.0 && cd freer-simple-1.2.1.0
edit stack.yaml # add the following stack.yaml
edit freer-simple.cabal  # relax the constraint on template-haskell
stack build --test --bench --no-run-benchmarks --fast
# stack.yaml
resolver: nightly-2019-09-29
extra-deps:
  - extensible-effects-5.0.0.1@sha256:2ed0bee04c8bf334358147da6d92ff31e9fbbefceb75ef3e408a0d858aec0cc6,9013

Handling the same effect multiple times with interpret and interpose

Here's self-containing example:

data MyEffect r where
    Execute :: MyEffect ()

makeEffect ''MyEffect

handleFirstEffect :: (LastMember IO effs) => MyEffect ~> Eff effs
handleFirstEffect = \case
    Execute -> liftIO $ print "handleFirstEffect"

handleSecondEffect :: (LastMember IO effs) => MyEffect ~> Eff effs
handleSecondEffect = \case
    Execute -> liftIO $ print "handleSecondEffect"

main :: IO ()
main = do
  runM
     $ interpret handleSecondEffect
     $ interpose handleFirstEffect execute

The programs prints only handleFirstSecond, but does not print handleSecondEffect. I would have expected to also print the latter, since interpose should allow someone to respond to the effect while leaving it unhandled.

Bug or is there's something I'm not understanding?

Wrapping an existing library - How to maintain state?

Hello! Thanks for this awesome library 🙏 😊

I'm trying to make an effect to represent actions from hint which defines an Interpreter monad that it is meant to be run using the function

runInterpreter :: Interpreter a -> IO (Either InterpreterError a)

I've created my own Interpreter (lets call it MyInterpreter) effect to provide a slightly better API (Text instead of String, newtypes where needed, etc...)

And then wrote a function to translate from my effect to the monad from the library:

asHint :: MyInterpreter a -> Interpreter a

My issue is the runInterpreter function from above, I don't want it to return Either, I prefer to use the Error effect, so I'm trying to implement a foo function for handling this:

foo
  :: forall effs a
  .  (Members '[IO, Error InterpreterError] effs)
  => Hint.Interpreter a
  -> Eff effs a
foo action = do
  result <- send (Hint.runInterpreter action)
  case result of
    Right x -> pure x
    Left e -> throwError e

So for example I could try to do

myProgram :: Member MyInterpreter effs => Eff effs ()
myProgram =
  runStatement "x = 42"
  runStatement "print x"

main = runM (handleError print (interpret foo myProgram))

The expected output would be 42, but what happens is that it fails saying that 42 is not in scope.
When using the library directly (without effects) this works properly.

My suspicion is that interpret foo is running Hint.runInterpreter once for each of the values of the GADT specifying the effect, making it lose completely the context.

Is there a way of gathering all the Interpreter values, and running Hint.runInterpreter on all of those?

Thanks in advance, any help is appreciated 🙏

Eff computations are coercible to each other

{-# LANGUAGE DataKinds #-}

import Control.Monad.Freer
import Control.Monad.Freer.Reader
import Control.Monad.Freer.State
import Data.Coerce

badness :: Eff '[Reader (Int, Int)] a -> Eff '[State Int] a
badness = coerce

boom :: (Int, Int)
boom = run $ evalState 17 (badness ask)

I believe the fix is to add a role annotation

type role Union nominal nominal

here:

-- | Open union is a strong sum (existential with an evidence).
data Union (r :: [Type -> Type]) a where
Union :: {-# UNPACK #-} !Word -> t a -> Union r a

(I can make a PR if welcome)

Inline simple effect primitives

I am wondering if it might make sense to mark the simple effect primitives of the form foo ... = send $ Effect ... like put from State with INLINE pragmas?

put :: forall s effs. Member (State s) effs => s -> Eff effs ()
put s = send (Put s)

Is there a reason this has not already been done? Functions like these seem like prime targets for human-directed inling.

Example of using Console

Further to #22, I think the README code example would be much more informative if it had an example of using Console somehow, and then two examples of this being interpreted: one with IO and the other pure.

As it is, it's kind of tricky to piece things together.

Thanks!

`runTrace` does not compose with other effects

Current function signature of runTrace is

runTrace :: Eff '[Trace] a -> IO a

which is less composable than

runTrace :: LastMember IO es => Eff (Trace ': es) a -> Eff es a
runTrace = interpret \case
  Trace s -> sendM $ putStrLn s

Do you think it'll be better to change it to that?

Add a function to map the effect list

After a bit of refactoring some freer-simple related code I ended up with this function:

mapEffs :: (Union effs ~> Union effs') -> Eff effs ~> Eff effs'
mapEffs f = loop where
    loop = \case
        Val a -> pure a
        E u q -> E (f u) (tsingleton $ qComp q loop)

It seems this might a useful thing to add to the library. Note that I have no idea if this implementation is a good one (or even if it makes sense really.)

Overlapping instances using paramerized effects

I would like to parameterize effects but they always lead to overlapping instances for me. A boiled-down example:

module Demo.OverlappingEffects where

import Control.Monad.Freer (Eff, Member, send)

data Box contents a where
    Receive :: Box contents [contents]
    Ship :: contents -> Box contents ()

-- | where we receive' a box of things and ship them out sep'rately
distribute :: forall contents effects. (Member (Box contents) effects) => Eff effects ()
distribute = do
    received <- receive'
    mapM_ ship' received
    where
        receive' = send Receive
        ship' c = send $ Ship c

But GHC tells me i'm being foolish:

    • Overlapping instances for Member (Box contents0) effects
      Matching givens (or their superclasses):
        Member (Box contents) effects
          bound by the type signature for:
                     distribute :: forall contents (effects :: [* -> *]).
                                   Member (Box contents) effects =>
                                   Eff effects ()
          at src/Demo/OverlappingEffects.hs:10:15-88
      Matching instances:
        instance (Data.OpenUnion.Internal.FindElem t r,
                  Data.OpenUnion.Internal.IfNotFound t r r) =>
                 Member t r
          -- Defined in ‘Data.OpenUnion.Internal’
      (The choice depends on the instantiation of ‘contents0, effects’)
    • In the ambiguity check for ‘distribute’
      To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
      In the type signature:
        distribute :: forall contents effects.
                      (Member (Box contents) effects) => Eff effects ()

I'm wondering if a) there is something I could do to my source to make this work e.g. move some qualifications around, b) this will forever be impossible with Freer-simple, please go away or, c) there is possibly a change to the Freer-simple implementation that would make this work.

If y'all think it's "c," I am happy to try to do the work. Not super confident in my type-level programming skills which is why I don't have a PR handy already.

Oh, and hi Alexis, I miss you.

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.