Coder Social home page Coder Social logo

extra's Introduction

Extra Hackage version Stackage version Build status

A library of extra functions for the standard Haskell libraries. Most functions are simple additions, filling out missing functionality. A few functions are available in later versions of GHC, but this package makes them available back to GHC 7.10. A few examples:

  • Control.Monad.Extra.concatMapM provides a monadic version of concatMap, in the same way that mapM is a monadic version of map.
  • Data.Tuple.Extra.fst3 provides a function to get the first element of a triple.
  • Control.Exception.Extra.retry provides a function that retries an IO action a number of times.
  • Data.Either.Extra.fromLeft is a function available in GHC 8.0 and above. On GHC 8.0 and above this package reexports the version from Data.Either while on GHC 7.10 and below it defines an equivalent version.

The module Extra documents all functions provided by this library. Modules such as Data.List.Extra provide extra functions over Data.List and also reexport Data.List. Users are recommended to replace Data.List imports with Data.List.Extra if they need the extra functionality.

Which functions?

When producing a library of extra functions I have been guided by a few principles. I encourage others with small useful utility functions contribute them here, perhaps as a temporary stop before proposing they join the standard libraries.

  • I have been using most of these functions in my packages - they have proved useful enough to be worth copying/pasting into each project.
  • The functions follow the spirit of the original Prelude/base libraries. I am happy to provide partial functions (e.g. fromRight), and functions which are specialisations of more generic functions (whenJust).
  • Most of the functions have trivial implementations that are obvious from their name/signature. If a beginner couldn't write the function, it probably doesn't belong here.
  • I have defined only a few new data types or type aliases. It's a package for defining new utilities on existing types, not new types or concepts.

Base versions

A mapping between base versions and GHC compiler versions can be found here.

Contributing

My general contribution preferences are available here. In addition, this repo contains some generated code which is checked in, namely src/Extra.hs and test/TestGen.hs. You can generate those files by either running runghc Generate.hs or ghci (which uses the .ghci file) and typing :generate. All PR's should contain regenerated versions of those files.

extra's People

Contributors

anniechen18 avatar boarders avatar bodigrim avatar cheecheeo avatar dbaynard avatar dyniec avatar felixonmars avatar franklinchen avatar galenhuntington avatar hurryabit avatar infinity0 avatar ivo-stefchev avatar jacereda avatar josephcsible avatar koterpillar avatar lev135 avatar mathnerd314 avatar mixphix avatar ndmitchell avatar pepeiborra avatar ryanglscott avatar snowleopard avatar sullyj3 avatar ysangkok avatar zliu41 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

extra's Issues

Make `notNull` for any `Foldable`

Hello, the notNull defined in Data.List.Extra, as a composition of not and null, is defined only for list, however, de null function works with any Foldable, so I think that it would make sense (and it would be very useful) for the notNull function to also work for any Foldable.
Some other functions of Data.List.Extra also would make sense if there where for any Foldable, such as allSame and anySame.

nubOrdBy definition

This is probably more of a question than an issue but is there any reason that nubOrd is not tail recursive, did you benchmark it to be faster as written? Also the red black tree implementation uses no strictness annotations, was it tested that they make no difference?

Add `flip foldMap`

flipped foldMap: (Foldable t, Monoid c) => t a -> (a -> c) -> c

It is similar to whenJust, but more pure, while whenJust is inherently effectful since it returns unit.

It can be used e.g. in the HTML AST of an Elm-style render function, when you want to optionally render something. In that case you'd wanna render nothing at all (mempty) when you get a Nothing.

In that case, the instantiation would be Maybe a -> (a -> HTML) -> HTML. If you had mbMyNumber, you could do flippedFoldMap mbMyNumber renderNumber instead of case mbMyNumber of Nothing -> mempty; Just x -> renderNumber x.

I am posting the issue here because I think the function is very general, and I was expecting whenJust to do just this. So maybe other people will have the same suspicion, and it would make sense to have this function next to the existing whenJust. The problem is, I don't know what to call this flipped foldMap.

On IRC, dsal made me aware that whenJust = flip traverse_. Maybe the fact that whenJust could be more general than it is, means that the general version should also be available? It seems weird to argue that flip traverse_ should be specialized but flip foldMap shouldn't. Either way, to have this added, we'd need a name, and the best name I can think of is whenJust, but it is taken. Would love to hear whether you think this function belongs here or not, and what it should be called.

ghci> :t flip traverse_ :: Monad m => Maybe a -> (a -> m ()) -> m ()
flip traverse_ :: Monad m => Maybe a -> (a -> m ()) -> m ()
  :: Monad m => Maybe a -> (a -> m ()) -> m ()

Thanks for your library, it has been very useful.

Add mconcatMap and mconcatMapM

I just found myself wishing that concatMapM had type (Monad m, Monoid o) => (a -> m o) -> [a] -> m o or even (Foldable f, Monad m, Monoid o) => (a -> m o) -> f a -> m o.

Many other functions like firstJust, allSame etc. could get similar generalizations.

Would it be ok to generalize the existing functions in Data.Monad.Extra and Data.List.Extra in this way? Would there be a point in adding generalized variants instead?

Add concatForM to Control.Monad.Extra

The following pattern seems to be extremely ubiquitous: fmap concat $ forM. A quick google search brings hundreds of matches.

We have concatMapM in Control.Monad.Extra, so perhaps we could add concatForM too? One possible implementation is simply concatForM = flip concatMapM. Can send a PR if you like this idea.

Add groupSortOn and groupSortBy

The obvious functions:

groupSortBy :: (a -> a -> Ordering) -> [a] -> [[a]]
groupSortOn :: Ord b => (a -> b) -> [a] -> [[a]]

Add (!?) function for lists

It would be nice for this function:

(!?) :: [a] -> Int -> Maybe a

to exist in a convenient place. Would you consider adding it to extra?

Build failures with GHC >= 9 in v1.5 to v1.7.6

src/System/IO/Extra.hs:76:41: error:
    Ambiguous occurrence ‘hGetContents'’
    It could refer to
       either ‘System.IO.hGetContents'’,
              imported from ‘System.IO’ at src/System/IO/Extra.hs:23:1-16
              (and originally defined in ‘GHC.IO.Handle.Text’)
           or ‘System.IO.Extra.hGetContents'’,
              defined at src/System/IO/Extra.hs:65:1
   |
76 | readFile' file = withFile file ReadMode hGetContents'
   |                                         ^^^^^^^^^^^^^

src/System/IO/Extra.hs:80:79: error:
    Ambiguous occurrence ‘hGetContents'’
    It could refer to
       either ‘System.IO.hGetContents'’,
              imported from ‘System.IO’ at src/System/IO/Extra.hs:23:1-16
              (and originally defined in ‘GHC.IO.Handle.Text’)
           or ‘System.IO.Extra.hGetContents'’,
              defined at src/System/IO/Extra.hs:65:1
   |
80 | readFileEncoding' e file = withFile file ReadMode $ \h -> hSetEncoding h e >> hGetContents' h
   |                                                                               ^^^^^^^^^^^^^

src/System/IO/Extra.hs:88:53: error:
    Ambiguous occurrence ‘hGetContents'’
    It could refer to
       either ‘System.IO.hGetContents'’,
              imported from ‘System.IO’ at src/System/IO/Extra.hs:23:1-16
              (and originally defined in ‘GHC.IO.Handle.Text’)
           or ‘System.IO.Extra.hGetContents'’,
              defined at src/System/IO/Extra.hs:65:1
   |
88 | readFileBinary' file = withBinaryFile file ReadMode hGetContents'
   |                                                     ^^^^^^^^^^^^^

src/System/IO/Extra.hs:121:16: error:
    Ambiguous occurrence ‘readFile'’
    It could refer to
       either ‘System.IO.readFile'’,
              imported from ‘System.IO’ at src/System/IO/Extra.hs:23:1-16
           or ‘System.IO.Extra.readFile'’,
              defined at src/System/IO/Extra.hs:76:1
    |
121 |         out <- readFile' file
    |                ^^^^^^^^^
cabal: Failed to build extra-1.5. See the build log above for details.

As a Hackage trustee, I have created revisions for these versions that should prevent users from getting these errors. See e.g. https://hackage.haskell.org/package/extra-1.7.6/revisions/.

Add flip const

Sometimes you want the function which takes two arguments and ignores the first. You can write that as:

flip const
\_ x -> x
const id
\_ -> id

Assuming that thing is called f, and we pass around a WHNF f x, the first two of those will leave the x captured. But in my view, the first two are also clearer to read. I however, don't guarantee that's true, my reasoning may be wrong....

It seems like having a flipConst or other function might be useful, with the best space behaviour it can do? Or maybe the restriction to only after people seq a function is just not helpful? Is there a good name for this function? Do lambdas really reduce differently for \x y -> ... vs \x -> \y -> ...? Or does the id make it different?

CC @josephcsible who brought this up first in HLint.

Make duration in MonadIO

duration2 :: MonadIO m => m a -> m (Seconds, a)
duration2 x = do
  start <- liftIO offsetTime
  res <- x
  end <- liftIO start
  return (end, res)

That works. Is there anything else that should be MonadIO'd? Not such a fan when it's merely a return type and liftIO works, but duration takes an IO so is harder

extra-1.6.4 test suite failure

This happened with GHC 8.4.1:

Test suite extra-test: RUNNING...
\(x :: IO Int) -> void (once x) == return ()
*** Failed! Falsifiable (after 4 tests): 
<<IO>>
Test suite extra-test: FAIL

The error occurs only spuriously, though.

Some functions I'm usin

Those are some functions I've been using a lot in parsers:

import qualified Control.Category as C
import Control.Monad
import Control.Applicative

composeMany :: (Alternative m, C.Category f) => m (f a a) -> m (f a a)
composeMany f = foldl (C.>>>) C.id <$> many f

($^) :: (Monad m) => m (a -> a) -> a -> m a
($^) f a = f `ap` return a

Where I'm parsing values that may come in any order, I create an initial state and a parser that returns a function updating that state, so I can just call composeMany parser $^ initialState.

Would you mind adding them? I'd think ($^) goes into Control.Monad.Extra, but I don't know where composeMany would go. If you want them, I can add docs and prepare a PR.

firstJust example in docs looks wrong

firstJust :: (a -> Maybe b) -> [a] -> Maybe b

Find the first element of a list for which the operation returns Just, along with the result of the operation. Like find but useful where the function also computes some expensive information that can be reused. Particular useful when the function is monadic, see firstJustM.

firstJust id [Nothing,Just 3]  == Just 3
firstJust id [Nothing,Nothing] == Nothing

should it not be ???

firstJust pure [Nothing,Just 3]  == Just 3
firstJust pure [Nothing,Nothing] == Nothing

OR

firstJust Just [Nothing,Just 3]  == Just 3
firstJust Just [Nothing,Nothing] == Nothing

Use clock package

First read http://chrisdone.com/posts/measuring-duration-in-haskell.

Now look at offsetTime:

-- | Call once to start, then call repeatedly to get the elapsed time since the first
--   call. Values will usually increase, unless the system clock is updated
--   (if you need the guarantee, see 'offsetTimeIncrease').
offsetTime :: IO (IO Seconds)
offsetTime = do
    start <- getCurrentTime
    return $ do
        end <- getCurrentTime
        return $ fromRational $ toRational $ end `diffUTCTime` start

This is described as "the naive, inaccurate solution" in the blog post.

The "nice" implementation uses getTime Monotonic from the clock package, and returns 1e-9 * fromRational (toNanoSecs $ end - start).

`Data.Foldable.Extra` not showing up on Hoogle

I can't seem to find the above module when adding extra-1.7.7 as a dependency to a project on GHC 8.10.2. Seeing as I wrote that library, I must not have regenerated the files properly when committing. I'm not sure how to do this properly since it was giving me errors when running the Generate.hs file both through cabal and ghci, saying it couldn't find the clock module...

Add zipFrom

zipFrom :: Enum a => a -> [b] -> [(a, b)]

Also add zipWithFrom

Test suite not compatible with QuickCheck 2.6

Noticed via Stackage's Haskell Platform build, which constrains QuickCheck.

$ cabal install extra --constraint 'QuickCheck < 2.7' --run-tests
...
test/TestGen.hs:34:90:
    Not in scope: ‘===’
    Perhaps you meant one of these:
      ‘==’ (imported from Prelude), ‘==>’ (imported from TestUtil)

test/TestGen.hs:35:90:
    Not in scope: ‘===’
    Perhaps you meant one of these:
      ‘==’ (imported from Prelude), ‘==>’ (imported from TestUtil)

test/TestGen.hs:36:90:
    Not in scope: ‘===’
    Perhaps you meant one of these:
      ‘==’ (imported from Prelude), ‘==>’ (imported from TestUtil)
Failed to install extra-0.3.1
cabal: Error: some packages failed to install:
extra-0.3.1 failed during the building phase. The exception was:
ExitFailure 1

Deprecate unnecessarily partial functions

We should deprecate replace and splitOn, and create alternatives for them that take a NonEmpty instead of crashing at runtime when their first parameter is empty.

Tests fail to build with GHCJS

[1 of 4] Compiling TestUtil         ( test/TestUtil.hs, /code/other-haskell/extra/dist-newstyle/build/x86_64-linux/ghcjs-8.4.0.1/extra-1.6.17/t/extra-test/build/extra-test/extra-test-tmp/TestUtil.js_o )

test/TestUtil.hs:10:6: error:
    Conflicting exports for ‘isWindows’:
       ‘module X’ exports ‘X.isWindows’
         imported from ‘System.FilePath’ at test/TestUtil.hs:33:1-27
         (and originally defined in ‘System.FilePath.Posix’)
       ‘module X’ exports ‘X.isWindows’
         imported from ‘System.Info.Extra’ at test/TestUtil.hs:34:1-29
   |
10 |     ,module X

This is no biggie, and I can workaround it easy by having an override

      extra          = dontCheckGHCJS super.extra;

but if it can be fixed, all the better!

Use GHC's definition of spanEnd?

Hoogling for spanEnd I found your definition and the one in ghc's Util, see
https://hackage.haskell.org/package/ghc-8.10.2/docs/src/Util.html#spanEnd

spanEnd :: (a -> Bool) -> [a] -> ([a], [a])
spanEnd p l = go l [] [] l
  where
  go yes _        rev_no [] = (yes, reverse rev_no)
  go yes rev_yes  rev_no (x:xs)
    | p x       = go yes (x : rev_yes) rev_no                  xs
    | otherwise = go xs  []            (x : rev_yes ++ rev_no) xs

This implementation is quite a bit more complicated than its specification spanEnd p l == reverse (span p (reverse l)). This suggests there were good reasons for the convoluted implementation.

So maybe switch to GHC's implementation?!

`concatUnzip` is just a special case of folding monoids

concatUnzip = (concat *** concat) . unzip

Found this function on Hoogle thanks to a 1HaskellADay challenge. I thought the implementation was clever, but there is actually a much simpler version: https://twitter.com/xgrommx/status/1374497119143223299

Because everything is a monoid, if you're brave enough.

(I don't expect you to take action on this issue, I just found it hilarious enough to share.)

Should fileEq on two files that don't exist return True?

Following on from #16, should fileEq on two files that don't exist be True? I'm inclined to think it should, since then you have the property that fileEq a a == True, which seems desirable, and also provides an implementation shortcut if met.

We can change it right now, since I only just released the new version, but I think it has to be today. CC @jacereda

Add nubOrd

Add a nub function that uses an Ord context and a balanced tree to run in O(n log n). Should not use containers, since that's a big dependency for a single function.

Split TestGen.hs

Currently it is problematic to add, for example, nubOrd to Data.List.NonEmpty.Extra, because nubOrd also exists in Data.List.Extra, and they clash in TestGen.hs. One solution is to split TestGen.hs to multiple modules, one per .Extra module.

`extra-1.0` incompatible with GHC 7.0

Please either make it compatible with GHC 7.0 again or add a base >= 4.4 constraint for the next release...

Building extra-1.0...
Preprocessing library extra-1.0...
[ 1 of 15] Compiling System.Info.Extra ( src/System/Info/Extra.hs, dist/build/System/Info/Extra.o )
[ 2 of 15] Compiling Numeric.Extra    ( src/Numeric/Extra.hs, dist/build/Numeric/Extra.o )
[ 3 of 15] Compiling Data.Tuple.Extra ( src/Data/Tuple/Extra.hs, dist/build/Data/Tuple/Extra.o )
[ 4 of 15] Compiling Data.List.Extra  ( src/Data/List/Extra.hs, dist/build/Data/List/Extra.o )
[ 5 of 15] Compiling Data.IORef.Extra ( src/Data/IORef/Extra.hs, dist/build/Data/IORef/Extra.o )
[ 6 of 15] Compiling Data.Either.Extra ( src/Data/Either/Extra.hs, dist/build/Data/Either/Extra.o )
[ 7 of 15] Compiling Control.Monad.Extra ( src/Control/Monad/Extra.hs, dist/build/Control/Monad/Extra.o )
[ 8 of 15] Compiling System.Directory.Extra ( src/System/Directory/Extra.hs, dist/build/System/Directory/Extra.o )
[ 9 of 15] Compiling Control.Exception.Extra ( src/Control/Exception/Extra.hs, dist/build/Control/Exception/Extra.o )
[10 of 15] Compiling System.Environment.Extra ( src/System/Environment/Extra.hs, dist/build/System/Environment/Extra.o )
[11 of 15] Compiling System.Time.Extra ( src/System/Time/Extra.hs, dist/build/System/Time/Extra.o )

src/System/Time/Extra.hs:70:30: Not in scope: `forkIOWithUnmask'

Document and test

The code needs thorough documentation and testing. Most of the code has been tested outside of extra, but it could do with additional testing.

Build failures with GHC HEAD

Just to get you ready for what's coming:

[ 2 of 17] Compiling Data.Either.Extra ( src/Data/Either/Extra.hs, dist/build/Data/Either/Extra.o )

src/Data/Either/Extra.hs:9:22: error:
    Ambiguous occurrence ‘fromLeft’
    It could refer to either ‘Data.Either.fromLeft’,
                             imported from ‘Data.Either’ at src/Data/Either/Extra.hs:12:1-18
                          or ‘Data.Either.Extra.fromLeft’,
                             defined at src/Data/Either/Extra.hs:21:1

src/Data/Either/Extra.hs:9:32: error:
    Ambiguous occurrence ‘fromRight’
    It could refer to either ‘Data.Either.fromRight’,
                             imported from ‘Data.Either’ at src/Data/Either/Extra.hs:12:1-18
                          or ‘Data.Either.Extra.fromRight’,
                             defined at src/Data/Either/Extra.hs:30:1

Documentation of `zipFrom` is misleading

-- | 'zip' against an enumeration.
--   Never truncates the output - raises an error if the enumeration runs out.
--
-- > \i xs -> zip [i..] xs == zipFrom i xs
-- > zipFrom False [1..3] == [(False,1),(True, 2)]

Never truncates the output

source:

-- Never truncates the output - raises an error if the enumeration runs out.

The fix depends on the actual intention, but since this is a released function, I suggest to change this to something like

Truncates the output if the enumeration runs out

Happy to provide a PR if that is the intent of the function.

Consider adding strict Var primitives

See the diff at haskell/haskell-language-server#1553. Inspired, but not directly following that code, my inclination would be:

modifyVar' :: Var a -> (a -> IO (a, b)) -> IO b
modifyVar_' :: Var a -> (a -> IO a) -> IO ()
writeVar' :: Var a -> a -> IO ()

All of which update the Var, and then, without the lock held, evaluate the a they just put inside the Var. CC @pepeiborra - does that sound plausible? I think that Ghcide having a custom Control.Concurrent.Strict wrapper that only exposes the strict variants is still likely to be useful for that project, but it could be done on top of those three.

ambiguous `withCurrentDirectory`

[ 9 of 15] Compiling System.Directory.Extra ( src/System/Directory/Extra.hs, dist/dist-sandbox-febc0bd9/build/System/Directory/Extra.o )

src/System/Directory/Extra.hs:7:5:
    Ambiguous occurrence ‘withCurrentDirectory’
    It could refer to either ‘System.Directory.Extra.withCurrentDirectory’,
                             defined at src/System/Directory/Extra.hs:28:1
                          or ‘System.Directory.withCurrentDirectory’,
                             imported from ‘System.Directory’ at src/System/Directory/Extra.hs:11:1-23

src/System/Directory/Extra.hs:7:5:
    Conflicting exports for ‘withCurrentDirectory’:
       ‘module System.Directory’ exports ‘System.Directory.withCurrentDirectory’
         imported from ‘System.Directory’ at src/System/Directory/Extra.hs:11:1-23
       ‘withCurrentDirectory’ exports ‘System.Directory.Extra.withCurrentDirectory’
         defined at src/System/Directory/Extra.hs:28:1

Due to System.Directory new version:

-- | Run an 'IO' action with the given working directory and restore the
-- original working directory afterwards, even if the given action fails due
-- to an exception.
--
-- The operation may fail with the same exceptions as 'getCurrentDirectory'
-- and 'setCurrentDirectory'.
--
-- @since 1.2.3.0
--
withCurrentDirectory :: FilePath  -- ^ Directory to execute in
                     -> IO a      -- ^ Action to be executed
                     -> IO a
withCurrentDirectory dir action =
  bracket getCurrentDirectory setCurrentDirectory $ \ _ -> do
    setCurrentDirectory dir
    action

proposal to add filesWithExtension

I would like to suggest adding a couple of small functions to System.Directory.Extra:

filesWithExtension :: FilePath -- directory
                   -> String   -- file extension
                   -> IO [FilePath]

fileWithExtension :: FilePath -- directory
                  -> String   -- file extension
                  -> IO (Maybe FilePath)

How does that sound?
If it is okay I am happy to open a PR for it.

Add Data.List.NonEmpty.Extra?

I use NonEmpty a lot and these are the functions I find useful:

-- | /O(n)/. Append an element to a list.
(|:) :: [a] -> a -> NonEmpty a
(|:) xs x = foldr cons (pure x) xs

-- | Append a list to a non-empty list.
appendl :: NonEmpty a -> [a] -> NonEmpty a
appendl (x :| xs) l = x :| (xs ++ l)

-- | Append a non-empty list to a list.
appendr :: [a] -> NonEmpty a -> NonEmpty a
appendr l nel = foldr cons nel l

There are certainly other useful functions for NonEmpty (e.g., the counterparts of many functions in Data.List.Extra), but I find these particularly useful since they obviate the need to use the partial fromList. So hopefully this is a reasonable starting point.

`group` functions using `NonEmpty`

I've now found myself several times using the following function:

collect :: Ord k => [(k, v)] -> [(k, NonEmpty v)]
collect = map (second NonEmpty.fromList) . groupSort

Having the type tell you that the value lists are non-empty often turns out to be very handy.

Would you be interested in including such a function and possibly similar variants for groupSortOn and groupSortBy?

I'm not sure about the naming so far. Would there be a point in deprecating the existing group functions in Data.List.Extra in favor of improved versions in Data.List.NonEmpty.Extra?

semigroups (and soon base!) contains a few more group variants that might serve as inspiration…

sleep test failure

do (a,_) <- duration $ sleep 1; return $ a >= 1 && a <= 1.1
*** Failed! Falsifiable (after 1 test):
extra-test: Test failed
CallStack (from HasCallStack):
  error, called at test/TestUtil.hs:47:28 in main:TestUtil
Test suite extra-test: FAIL

The test failed two times in a row. The computer is not top notch, but is not terrible either: a rather old iMac with Core i3 550 @ 3.2GHz, but it was under very heavy load (compiling multiple Haskell packages and a couple of GHC versions at the same time). So, maybe, it would not be a bad idea to slightly increase the upper bound just in case...

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.