Git Product home page Git Product logo

mtl's People

Contributors

akrmn avatar bezirg avatar chessai avatar ddssff avatar dmjio avatar duog avatar ekmett avatar elvishjerricco avatar emilypi avatar endgame avatar fishtreesugar avatar fisx avatar fumieval avatar hvr avatar jappeace avatar jaspa avatar kozross avatar matobet avatar meteficha avatar mrbliss avatar obadz avatar ocramz avatar owickstrom avatar phadej avatar rcook avatar relrod avatar ryanglscott avatar saurabhnanda avatar telmich avatar tmcgilchrist 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mtl's Issues

Overview and introductory documentation improvements

Hi! My first time posting issues here, so just wanted to start by
saying thanks for maintaining MTL! It's a life saver library that I
use in practically all projects. 🙌

OK, so I'm at ZuriHac and focusing on documentation improvements in
the Haskell ecosystem. I've noticed the documentation is a little thin
and confusing in terms of "at a first sight" experience, perhaps
coming in as a Haskell novice wondering what this MTL thing might be.

This issue is meant as a starting point for further discussion and
contributions, not as a complaint. It focuses on the "first contact"
aspect and the README. I'd be happy to send PRs once we are one the
same page on what to do.

Current state of things

On GitHub:

The README only links to the Hackage page. The website URL points to
the MTL wiki (http://www.haskell.org/haskellwiki/Monad_Transformers).

On Hackage:

http://hackage.haskell.org/package/mtl

The package description is:

Monad classes using functional dependencies, with instances for
various monad transformers, inspired by the paper Functional
Programming with Overloading and Higher-Order Polymorphism, by Mark
P Jones, in Advanced School of Functional Programming, 1995
(http://web.cecs.pdx.edu/~mpj/pubs/springschool.html).

Looking at the hyperlinked paper, the abstract says:

[...] Focusing on practical applications rather than implementation or theo-
retical details, these notes examine a range of extensions that provide
more flexible type systems while retaining many of the properties that
have made the original Hindley/Milner system so popular. [...]

There is no link to the Wiki, the "Home page" link goes back to the GitHub repo.

Module docs on Hackage:

Many modules already have great documentation and examples in the
Haddock module documentation! 👍

The same paper which is linked in the description, is also linked in
several modules (http://web.cecs.pdx.edu/~mpj/pubs/springschool.html),
as "Inspired by the paper ...".

On the Wiki:

https://wiki.haskell.org/Monad_Transformers

The page describes not only MTL, but different Haskell implementations
of monad transformers and their history. Later, it also compares the
libraries, e.g. "Shall I use MTL or transformers?"

The links at the bottom are:

Reflection on the current state of things:

  • Coming in via the GitHub page as a new user of MTL, I'd already be a
    bit confused where to go next and how to learn more about the
    package.
  • The wiki page seems more like a historically interesting document
    for implementers, not a useful start page for users.
  • The paper linked in the package description does not seem focused on
    MTL (I have just skimmed it).

Ideas & Possible Improvements

  1. Discuss what purpose each document should have; README vs. Hackage
    vs. Wiki page(s).
  2. The README could perhaps summarize, with
    short descriptions and possible uses, the different monad
    transformers and link to the respective modules on Hackage.
  3. We could also add external links to tutorials, books and such for
    the different transformers, in the README.
  4. Provide only a short Haddock description for the package, and mainly
    use and refer to the README.

So to summarize, concentrate the overview and introductory
documentation in the README and improve it.

Other Documents

There are other things we could work on and link from the README:

  • Add an FAQ document that describes common pitfalls, considerations, etc
  • Link to a detailed comparison with transformers (extract from the
    wiki or make that a separate page on GitHub or the wiki).
  • Link the inspiration paper once, and improve those module
    descriptions that are a bit lacking. At least for me, that paper
    does not seem to be helpful for a new user of MTL.

I hope this provides a useful starting point for working on the MTL
overview and introductory documentation, and happy to get feedback and
discussions going!

By the way, @gilligan helped me put this issue together.

Cheers!

No MonadError instance for Maybe or []

There is a MonadError instance defined for Either, but neither Maybe nor List ([]) even though the transformer versions of those types are defined.

As it stands, users who may wish to treat a failure as a Nothing or empty list must define Orphaned instances.

Document the MonadWriter laws

More "positive" laws relating pass and listen to tell are conspicuously absent in both the mtl and transformers. This expands upon issue #25.

We currently at best have laws stated in terms of runWriterT which is unsatisfying.

ApplicativeReader

The Monad constraint on MonadReader is a bit too constraining for me; I'd really like to loosen that constraint to Applicative (or looser?) while breaking the least amount of code possible.

So now that we've made Applicative a superclass of Monad, that would make such a transition considerably easier. However, simply changing Monad to Alternative, while it shouldn't break instances, would break client code that use the Monad class but don't explicitly declare (Monad m, MonadReader m) =>.

It seems fairly safe to assume there's more client code than there are instances, one possibility would be to have something like the following:

class Applicative m => ApplicativeReader r m | m -> r where
    ask :: ...
    local :: ...
    reader :: ...

class (Monad m, ApplicativeReader m) => MonadReader m
instance (Monad m, ApplicativeReader m) => MonadReader m

Then, the only thing people would have to do would be to replace the name MonadReader with ApplicativeReader in all their instances. This might cause some problems for people who don't update their instances and have have OverlappingInstances turned on; it would seem preferable to make MonadReader a closed typeclass or a typeclass synonym.

Making MonadReader a typeclass synonym is possible with ConstraintKinds, but would also require ConstraintKinds to be enabled in all code that mentions the MonadReader constraint.

Document what Strict and Lazy mean

Affects:

Control.Monad.State.Strict
Control.Monad.Writer.Strict
Control.Monad.RWS.Strict

From Ben Gamari:

In general it would be nice if the notion of strictness were better
addressed in the major libraries' documentation. It's a nuanced
issue which is not fully captured by a ".Lazy" or ".Strict" in the
module name.

Suggested addition tryError (originally tryExceptT)

It seems to me that this function might make a useful addition to Control.Monad.Except:

-- | ExceptT analog to the 'try' function.
tryExceptT :: Monad m  => ExceptT e m a -> ExceptT e m (Either e a)
tryExceptT = lift . runExceptT

Cut a release for GHC 8.4

The GHC 8.4.1 release is quickly approaching and i would like to have all of the submodules finalized by next alpha. For this we will likely need a new release.

Encapsulate IO exceptions in Monad IO m, MonadError e m

I'm actually not sure whether this is an issue, or if it fits the project goals at all, but I keep wondering why we can't have an encapsulation of core exceptions from IO actions (since they are far too common) under a more type-safe approach such as MonadError e m.

What I'm thinking about is something like

import Control.Monad.Except
import Control.Exception (Exception (..), try)

liftErrorIO :: (Exception e, MonadIO m, MonadError e m) => IO a -> m a
liftErrorIO = liftIO . try >=> either throwError return

liftedBracket :: (Exception e, MonadIO m, MonadError e m) =>
                 m a
              -> (a -> m b)
              -> (a -> m c)
              -> m c
liftedBracket acquire release comp = do
  resource <- acquire
  result <- catchError (comp resource) (\e -> release resource >> throwError e)
  _ <- release resource
  return result

Make ((,) a) an instance of MonadWriter

instance Monoid w => MonadWriter w ((,) w) where
    writer = swap
    tell = flip (,) ()
    listen ~(w, a) = (w, (a, w))
    pass ~(w, ~(a, f)) = (f w, a)

It might be necessary to put in a bit of CPP as the Monad instance of Monoid w => Monad ((,) w) only came around in base version 4.9.0.0, but to me this still seems like a worthwhile addition with no significant downsides.

Cont instances for StateT

The MonadCont for both Lazy and Strict StateT uses liftCallCC' from their respective modules.

However, if you look at the documentation for these functions, they both say:

It does not satisfy the laws of a monad transformer.

(As opposed to liftCallCC, which presumably does.)

Is the documentation for liftCallCC' incorrect (in which case this is something that should be fixed in transformers), or is mtl really using a function that prevents the monad transformer laws from being satisfied?

(This is also true in pre-transformers mtl, so it's highly possible that the behaviour was just copied over. The comment about not satisfying the monad transformer laws was not added until transformers-0.2.0.0... which is also the first version of transformers used by mtl.)

Module ‘Control.Monad.Error.Class’ does not export ‘Error(..)’

I'm experimenting with mtl master and encountered this issue with tls:

Network/TLS/ErrT.hs:19:35: error:
    Module ‘Control.Monad.Error.Class’ does not export ‘Error(..)’
   |
19 | import Control.Monad.Error.Class (Error(..))
   |                                   ^^^^^^^^^

I didn't see this mentioned in the changelog. Possibly an oversight?!

Uneasy with example using `fromJust`

Reader.hs documentation has an example that makes me very uneasy because it uses fromJust. I think code snippets make a big impression on newcomers and the example code to illustrate Reader is not anything anyone would really write because it doesn't account for errors.

lookupVar :: String -> Bindings -> Int
lookupVar name bindings = fromJust (Map.lookup name bindings)

Re-export evalCont/evalContT?

These two functions are present in transformers but not mtl:

  • evalCont :: Cont r r -> r -- The result of running a CPS computation with the identity as the final continuation.
  • evalContT :: Monad m => ContT r m r -> m r -- The result of running a CPS computation with return as the final continuation.

Should they be re-exported? If so, I will prepare a PR.

Adding a proper ListT to transformers and this package

I think we should add a type equivalent to the following to transformers (and mtl):

newtype ChoiceT m a = ChoiceT { runChoiceT :: m (Maybe (ChoiceT m a)) }

This is a monad transformer, while it's well-known that the existing ListT is not.

And perhaps we should add the relevant MonadChoice class here (subject to design discussion)

Ideally this would happen in cooperation between the two libraries, hence why I'm opening it here. We would at least need all the instances to lift MonadX through ChoiceT

Bikeshedding name suggestions: ChoiceT, StreamT, NonDetT, ...

No instances for recently-added monads from transformers

Control.Monad.Trans.Accum was added in transformers 0.5.3.0, but currently it's slightly painful to use because it doesn't have the usual MonadState, MonadReader, etc instances yet.

Whether it should get a MonadWriter instance that lifts the operations to the inner monad or handles them itself is a question.

SelectT was also added in transformers 0.5.3.0 and similarly lacks instances.

Mtl 2.3 Release Prep

This is release prep for the 2.3 release of mtl.

TODO


  • Add existing typeclass instances for SelectT
  • MonadAccum (including documentation)
  • MonadSelect (including documentation)
  • Compatibility with transformers-0.6
  • Changelog entries
  • Remove all re-exports
  • Version narrowing
  • Cut a release

`mtl-2.0.1.0` fails to build with recent `base`

I know this isn't the latest version of mtl, but the problem is that mtl-2.0.1.0 claims to work with base<6 which obviously isn't true, letting cabal-install select that version of mtl in some cases instead of trying harder to find a different install plan. The compile error is:

Configuring mtl-2.0.1.0...
Building mtl-2.0.1.0...
Preprocessing library mtl-2.0.1.0...
[ 1 of 21] Compiling Control.Monad.Writer.Class ( Control/Monad/Writer/Class.hs, dist/build/Control/Monad/Writer/Class.o )
[ 2 of 21] Compiling Control.Monad.State.Class ( Control/Monad/State/Class.hs, dist/build/Control/Monad/State/Class.o )
[ 3 of 21] Compiling Control.Monad.Reader.Class ( Control/Monad/Reader/Class.hs, dist/build/Control/Monad/Reader/Class.o )
[ 4 of 21] Compiling Control.Monad.RWS.Class ( Control/Monad/RWS/Class.hs, dist/build/Control/Monad/RWS/Class.o )
[ 5 of 21] Compiling Control.Monad.Identity ( Control/Monad/Identity.hs, dist/build/Control/Monad/Identity.o )
[ 6 of 21] Compiling Control.Monad.Error.Class ( Control/Monad/Error/Class.hs, dist/build/Control/Monad/Error/Class.o )

Control/Monad/Error/Class.hs:93:18: Not in scope: ‘catch’
Failed to install mtl-2.0.1.0
Updating documentation index /home/hvr/.cabal/share/doc/ghc-7.8.2/index.html
cabal: Error: some packages failed to install:
mtl-2.0.1.0 failed during the building phase. The exception was:
ExitFailure 1

Merge Control.Monad.Writer.CPS from writer-cps-mtl

Currently transformers has a type called Control.Monad.Trans.Writer.CPS.WriterT that does not have accompanying MonadWriter / lifting instances in MTL. These instances are currently implemented as orphan instances in writer-cps-mtl. It should be possible to pretty much just copy over the modules defined in that package over to mtl to gain support.

Deprecate Error and ErrorList classes

The existence of these classes is extremely strange to me. I think now that ListT and ErrorT are being removed, these can be deprecated. What do others think? @haskell/core-libraries-committee

Also, this needs a proper library mailing list proposal

MonadReader instance for ContT has bad semantics

We'd expect local id == id, but this isn't true for ContT.

Let:

localTheCont :: MonadReader Int m => ContT r m ()
localTheCont = ContT $ \c -> local (+1) (c ())

test1 :: MonadReader Int m => ContT r m Int
test1 = localTheCont >> ask

test2 :: MonadReader Int m => ContT r m Int
test2 = local id localTheCont >> ask

then

runReader (evalContT test1) 1 == 2
runReader (evalContT test2) 1 == 1

Breaking apart the instance reveals what goes wrong:

  local id localTheCont
= ContC $ \c ->
    i <- ask
    local id $ runContC localTheCont (local (const i) . c)
= ContC $ \c ->
    i <- ask
    local id $ local (+1) ((local (const i) . c) ())
= ContC $ \c ->
    i <- ask
    local (const i . (+1) . id) (c ())
= ContC $ \c ->
    i <- ask
    local (const i) (c ())

Removing the instance would undoubtedly cause too much breakage, but perhaps a warning in the docs is warranted.

Generic lifting of MonadCont

It's possible to define a liftCallCC for any MonadTrans as follows:

liftCallCC :: (MonadTrans t, Monad (t m), Monad m)
           => CallCC m (t m a) b -> CallCC (t m) a b
liftCallCC callCC main = join . lift . callCC $ \exit ->
  return $ main (lift . exit . return)

This satisfies the uniformity condition as long as you assume callCC is algebraic; that is,

callCC (\exit -> f (g >=> exit) >>= g) = callCC f >>= g

Which should always be true, except perhaps for StateT's instance of MonadCont, since that doesn't satisfy the uniformity condition.

I've sketched a proof here.

This has been used in the wild by @ekmett in free.

Given its usefulness for defining MonadCont instances for novel monad transformers, I feel the generic liftCallCC or some variant thereof should be added to mtl (or transformers).

There is no relation between MonadFail and MonadError

Currently there is no relation between MonadFail and MonadError. And this is bad.

What is the right way to report errors if you know that they are strings and you want to be able to catch them in pure code? Currently we have such options: Either String, MonadFail and MonadError. Either String is not very general, so we have MonadFail and MonadError. Unfortunately, they are incompatible in both ways! What to do? Well, I propose creating instance instance (MonadError String a) => MonadFail a

Add MINIMAL pragmas

From a quick look, the following classes would benefit from MINIMAL pragmas since they have recursive method definitions:

  • MonadState
  • MonadWriter

Maybe some others that I missed.

Stricter Writer

Hi,

I made the packages writer-cps-mtl and writer-transformers-mtl which implement a stricter writer monad transformer in continuation passing style as was discussed before on the Haskell mailing list etc

See also the current reddit discussion:
https://www.reddit.com/r/haskell/comments/50hf2s/stricter_writert_and_rwst_replacements/

Would you be interested in including this into mtl? If not it can also exist as a separate package, but I guess it would be nice to have a well-behaving writer around in the standard toolbox.

Daniel

ContT is strange?

hello, everyone.
I found ContT a bit weird.

newtype ContT r m a = ContT { runContT :: (a -> m r) -> m r }

Why can't we define it like this?

newtype ContT r m a = ContT {runContT :: (m a -> m r) -> m r}

evalContT :: (Monad m) => (m a -> m r) -> ContT r m a -> m r
evalContT f m = runContT m f

instance Functor m => Functor (ContT r m) where
  fmap f m = ContT $ \c -> runContT m (c . fmap f)

instance Applicative m => Applicative (ContT r m) where
  pure x = ContT ($ pure x)
  f <*> v = ContT $ \c -> runContT f $ \g -> runContT v (\tmp -> c (g <*> tmp))

-- never del this
-- res <- runContT <$> (k <$> x)
-- res c
instance (Monad m) => Monad (ContT r m) where
  m >>= k = ContT $ \c -> runContT m ((<$>) k >=> (($ c) . runContT))

instance MonadTrans (ContT r) where
  lift m = ContT $ \g -> g m

instance MonadIO m => MonadIO (ContT r m) where
  liftIO io = ContT $ \c -> c (liftIO io)

https://github.com/EMQ-YangM/fused-effects-cont/blob/5fd9dc23b3640a9702acacdf55f450dfb6c719db/src/Cont.hs#L24-L52
It seems more normal to look at it this way.

I hope I can use ContT in fused-effects.
If I have any mistakes, please let me know.

instance (MonadError e f, MonadError e g) => MonadError e (Product f g)

Is there a technical reason why this instance doesn't exist? It seems well-behaved (some sanity-check proofs are at the bottom of the page).

fstP :: Product f g a -> f a
fstP (Pair a _) = a

sndP :: Product f g a -> g a
sndP (Pair _ a) = a

instance (MonadError e f, MonadError e g) => MonadError e (Product f g) where
  throwError e = Pair (throwError e) (throwError e)
  catchError (Pair ma mb) f = Pair (catchError ma (fstP . f)) (catchError mb (sndP . f))

catchError m throwError = m

catchError (Pair f g) throwError
= { inline catchError }
Pair (catchError f (fstP . throwError)) (catchError g (sndP . throwError))
= { inline throwError }
Pair 
  (catchError f (fstP . (\e -> Pair (throwError e) (throwError e)))
  (catchError g (sndP . (\e -> Pair (throwError e) (throwError e)))
= { inline (.) }
Pair 
  (catchError f (\e -> fstP (Pair (throwError e) (throwError e)))
  (catchError g (\e -> sndP (Pair (throwError e) (throwError e)))
= { eta-reduction }
Pair 
  (catchError f (\e -> throwError e))
  (catchError g (\e -> throwError e))
= { eta-reduction }
Pair 
  (catchError f throwError)
  (catchError g throwError)
= { hypothesis }
Pair f g
catchError (throwError e) pure = pure e

catchError (throwError e) pure
= { inline throwError }
catchError (Pair (throwError e) (throwError e)) pure = pure e
= { inline catchError }
Pair (catchError (throwError e) (fstP . pure)) (catchError (throwError e) (sndP . pure))
= { inline pure, (.) }
Pair 
  (catchError (throwError e) (\x -> fstP (Pair (pure x) (pure x)))) 
  (catchError (throwError e) (\x -> sndP (Pair (pure x) (pure x))))
= { eta-reduction }
Pair 
  (catchError (throwError e) (\x -> pure x)) 
  (catchError (throwError e) (\x -> pure x))
= { eta-reduction }
Pair 
  (catchError (throwError e) pure) 
  (catchError (throwError e) pure)
= { hypothesis }
Pair (pure e) (pure e}
= { pure }
pure e

Control.Monad.State.Class.modify' does not behave like Control.Monad.Trans.State.Lazy.modify'

Control.Monad.State.Class.modify' is defined as follows.

modify' :: MonadState s m => (s -> s) -> m ()
modify' f = state (\s -> let s' = f s in s' `seq` ((), s'))

According to the instance of MonadState s (StateT s m) , this is equivalent to:

modify' f = state (\s -> let s' = f s in s' `seq` ((), s'))
          = StateT (return . (\s -> let s' = f s in s' `seq` ((), s')))
          = StateT (\s -> return (let s' = f s in s' `seq` ((), s')))

Because (let s' = f s in s' `seq` ((), s')) is encapsulated by return,
f s does not evaluated when modify f is evaluated.

I think this behavior is NOT desired.
In the transformers package, modify' is defined as follows.

modify' :: (Monad m) => (s -> s) -> StateT s m ()
modify' f = do
    s <- get
    put $! f s

With this definition, modify' f evaluates f s, as expected.

It seems that pull request #13 fixes this issue, but it haven't been merged for a few years.

Alternative instance MonadState s (ContT r m)

I notice that instead of requiring MonadState s m, it's possible to require MonadReader s m:

instance MonadReader s m => MonadState s (ContT r m) where
    get = ContT (\smr -> ask >>= smr)
    put s = ContT (\umr -> local (\_ -> s) (umr ()))

Is this preferable?

Add MonadDeclare

swagger2 makes use of a DeclareT monad transformer which lies between the WriterT and StateT.
It also provides an mtl-style MonadDeclare type class with some laws.
Since the construction is not specific to swagger2, it might make sense to add it to mtl and transformers.

A corresponding issue for transformers is here.

The rationale for Declare is generating a list of Swagger schema definitions.
To avoid duplicates and to fix recursive schemas we need to look at the previous definitions.
But we don't want a full State because we don't want someone to accidentally erase/change all/some previous definitions in a ToSchema instance for a user data type.
The laziness plays nice part here and allows (mutually) recursive schemas to be written easily (e.g. see sources for declareSchemaRef).

Extraneous Error constraints

Many instances for MonadError have Error constraints that are completely unused. In particular, the MonadError instance for Either does not use its Error constraint. This does nothing except restrict generality.

Missing laws

The laws for MonadState, etc. are missing from the haddocks.

It may be a good idea to add them.

Control.Monad.State.Strict.modify is lazy

I've had programs that repeatedly modified state leak memory because modify does not force the f s thunk.

This is surprising in a library with "strict" in its name..

Documentation suggests using deprecated `Error` class

The documentation for MonadError says "In these cases you will have to explicitly define instances of the Error and/or MonadError classes."

Error links to Control.Monad.Error.Class. If you try to import that in a Haskell module, you get deprecation warnings:

MyModules.hs:208:14: Warning:
    In the use of type constructor or class ‘Error’
    (imported from Control.Monad.Error.Class, but defined in transformers-0.4.1.0:Control.Monad.Trans.Error):
    Deprecated: "Use Control.Monad.Trans.Except instead"

But Control.Monad.Trans.Except does not export an Error class.

Cut a new release of mtl

mtl now provides a number of useful, unreleased changes (among them instances for Control.Monad.Trans.Writer.CPS and Control.Monad.RWS.CPS which were introduced in transformers-0.5.6.2).

Can we get a new release of this library in time for GHC 8.10, or has that ship sailed?

MTL doesn't adhere to PVP as it re-exports e.g. Control.Monad

This is subtle issue. But when you do

import Prelude ()
import Prelude.Compat --base-compat-0.11

import Control.Monad.Reader -- mtl-2.2.2

Then the fail is ambiguous.

it's my own fault, that I imported Control.Monad.Reader unqualified, but still this is surprising and nasty.

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.