Code Monkey home page Code Monkey logo

fluokitten's People

Contributors

blueberry 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

fluokitten's Issues

Functor and Applicative instance for Map

  1. Variadic fmap for maps sometimes fails with ArityException:
    (fmap subs {:a "abc" :b "cde"} {:a 1 :c 2})
  2. fapply for maps sometimes return result of incorrect type:
    (fapply {:a (partial subs "abc") :b (partial subs "abc")} {:a 1 :c 2})
    • expected: value of type (Map Keyword String) (first parameter is of type (Map Keyword (IFn [Int -> String])), second parameter is of type (Map Keyword Int), so we fapply (Applicative (IFn [Int -> String])) to (Applicative Int) and shall obtain (Applicative String) (type annotation of typed clojure is used)).
    • result: {:a "bc" :c 2} - Heterogeneous map.
  3. Strange behaviour for maps containing nils as keys:
    (fapply {:a inc nil dec} {:a 1 :b 2}) = {:a 2 :b 1}
    while
    (fapply {:a inc :c dec} {:a 1 :b 2}) = {:a 2 : b 2}

In fact both fapply and variadic fmap for maps works only in case of maps of identical keys, or functions with variadic homogeneus parameters.

Consider type annotation

Hey, it would be nice to also have type annotations using core.typed. Have you thought about it?

thx for the project!!

Inconsistency in protocol realisations for sequential collections

  1. Using 'fmap' as variadic function requires instance of Applicative. Proof: you can define 'fapply' as (partial fmap apply) and '(pure x)' as (fmap #(identity x)) (it is impossible to write this realisation of 'pure' in clojure due to the absence of return-type polymorphism). Looks like this point was discussed in Issue #12 .

  2. Lists and other sequentional collections can be instances of Applicative and Monad in two different ways: as fixed-size vectors with componentwise operations, and as an undetermenistic computation (undetermenistic computation is more common and it is a default behaviour in Haskell):

    1. (fapply [inc dec] [3 4]) = [4 3]
    2. (fapply [inc dec] [3 4]) = [4 2 5 3]

    If variadic 'fmap' and 'fapply' are defined independently, then inequality
    (not= (fmap apply [inc dec] [1 2]) (fapply [inc dec] [1 2])) is an unexcpected behaviour from my point of view.
    And in the case of sequentional collections (i) is chosen for 'fmap' and (ii) for 'fapply'.

  3. Every Monad has an inherited Applicative Functor structure, but in the library Monad and Applicative protocol realisations for sequential collections are incoherent (see (2)) which is an unexpected behaviour from my point of view.

Implement mdo syntactic sugar for chained binds

There should be a macro for helping with chained binds. This macro, mdo should be modeled on Haskell's do, but also take into account how Clojure's let form works. There should be a return implementation available inside the macro, that will be a shortcut to (pure m).
It should look something like this:

(mdo [a


b
c ]

)

Implement the vararg version of fmap through fapply

Currently, the only difference between the vararg fmap and vararg fapply is that the vararg fmap is (fapply (pure x f) x). That is a bit redundant, and can be shortened, so Functor implementations only need to implement the two-arg fmap, while core.fmap should wrap its f argument with pure and call fapply. This implementation is also more consistent with Haskell's and avoids having to explicitly define functor laws for varargs.

Multiarity fmap is no longer fmap

While reading the Fluokitten documentation I noticed that it's often touted as an advantage of implementing these concepts in Haskell that fmap is able to variadic. Later, it's pointed out Haskell requires using (<*>) or ap to achieve this effect.

The problem is that variadic fmap just isn't fmap—it's a stronger requirement than just being a Functor. In particular, it imbues a kind of sequencing on your "Functor" which is above the call of duty for just having a Functor—you're opening up each of the boxes in sequence, calling the combining function, then closing them back. A normal functor should disallow that.

One place this distinction shows up is that it prevents you from extracting the commonalities between various applicative instances of Lists/vectors. The applicative instance of vector in Fluokitten is the "Cartesian applicative"

pure a = [a]
fs <*> xs = [f x | f <- fs, x <- xs]

> [(+1), (+2)] <*> [1,2,3]
[2,3,4,3,4,5]

But there's also a law-abiding applicative instance for Lists/vectors of any fixed length. Often this is implemented with infinite lists in Haskell

pure a = repeat a  -- [a, a, a, a, ...]
fs <*> xs = zipWith (\f x -> f x) fs xs

> [(+1), (+2)] <*> [1,2,3]
[2,4]

This is all well and good—these are distinct types. However, it's important to note that they both have identical Functor instances so long as fmap is not variadic.

In fact, in Haskell we have the guarantee that there is exactly one non-pathological function with the type

fmap :: (a -> b) -> (f a -> f b)

and satisfying fmap id = id. That's the power of the Functor laws.


Obviously, it's a design choice in Fluokitten to include variadic fmap or not, but it's a patent inaccuracy in the documentation to call an interface Functor if it provides a variadic fmap.

[Q] On inconsistent behavior in doc and 0.6.0 release

Hi, I've been toying around fluokitten and which is very fun. However, I found there're some
inconsistent behaviors between document at Fluokitten Extensions of Clojure Core and the result.

For example;

The doc says

(fmap inc (empty (seq [1]))) => (empty (seq [2]))
(fmap inc (lazy-seq [])) => (lazy-seq [])

However, what I got is

(fmap inc (empty (seq [1]))) => ()
(fmap inc (lazy-seq [])) => ()

Is this correct?

Running Compiled Jar File Causes ExceptionInInitializerError

On [org.clojure/clojure "1.8.0"] and using :uberjar {:aot :all}
I'm using the clojure:onbuild docker image it runs on openjdk 8 using the openjdk:8-alpine image and leiningen 2.7.1
Running the jar file causes

Exception in thread "main" java.lang.ExceptionInInitializerError
	at java.lang.Class.forName0(java.base@9-internal/Native Method)
	at java.lang.Class.forName(java.base@9-internal/Class.java:378)
	at clojure.lang.RT.classForName(RT.java:2168)
	at clojure.lang.RT.classForName(RT.java:2177)
	at clojure.lang.RT.loadClassForName(RT.java:2196)
	at clojure.lang.RT.load(RT.java:443)
	at clojure.lang.RT.load(RT.java:419)
	at clojure.core$load$fn__5677.invoke(core.clj:5893)
	at clojure.core$load.invokeStatic(core.clj:5892)
	at clojure.core$load.doInvoke(core.clj:5876)
	at clojure.lang.RestFn.invoke(RestFn.java:408)
	at clojure.core$load_one.invokeStatic(core.clj:5697)
	at clojure.core$load_one.invoke(core.clj:5692)
	at clojure.core$load_lib$fn__5626.invoke(core.clj:5737)
	at clojure.core$load_lib.invokeStatic(core.clj:5736)
	at clojure.core$load_lib.doInvoke(core.clj:5717)
	at clojure.lang.RestFn.applyTo(RestFn.java:142)
	at clojure.core$apply.invokeStatic(core.clj:648)
	at clojure.core$load_libs.invokeStatic(core.clj:5774)
	at clojure.core$load_libs.doInvoke(core.clj:5758)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.core$apply.invokeStatic(core.clj:648)
	at clojure.core$require.invokeStatic(core.clj:5796)
	at clojure.core$require.doInvoke(core.clj:5796)
	at clojure.lang.RestFn.invoke(RestFn.java:408)
	at uncomplicate.fluokitten.core$loading__5569__auto____3776.invoke(core.clj:9)
	at uncomplicate.fluokitten.core__init.load(Unknown Source)
	at uncomplicate.fluokitten.core__init.<clinit>(Unknown Source)
	at java.lang.Class.forName0(java.base@9-internal/Native Method)
	at java.lang.Class.forName(java.base@9-internal/Class.java:378)
	at clojure.lang.RT.classForName(RT.java:2168)
	at clojure.lang.RT.classForName(RT.java:2177)
	at clojure.lang.RT.loadClassForName(RT.java:2196)
	at clojure.lang.RT.load(RT.java:443)
	at clojure.lang.RT.load(RT.java:419)
	at clojure.core$load$fn__5677.invoke(core.clj:5893)
	at clojure.core$load.invokeStatic(core.clj:5892)
	at clojure.core$load.doInvoke(core.clj:5876)
	at clojure.lang.RestFn.invoke(RestFn.java:408)
	at clojure.core$load_one.invokeStatic(core.clj:5697)
	at clojure.core$load_one.invoke(core.clj:5692)
	at clojure.core$load_lib$fn__5626.invoke(core.clj:5737)
	at clojure.core$load_lib.invokeStatic(core.clj:5736)
	at clojure.core$load_lib.doInvoke(core.clj:5717)
	at clojure.lang.RestFn.applyTo(RestFn.java:142)
	at clojure.core$apply.invokeStatic(core.clj:648)
	at clojure.core$load_libs.invokeStatic(core.clj:5774)
	at clojure.core$load_libs.doInvoke(core.clj:5758)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.core$apply.invokeStatic(core.clj:648)
	at clojure.core$require.invokeStatic(core.clj:5796)
	at clojure.core$require.doInvoke(core.clj:5796)
	at clojure.lang.RestFn.invoke(RestFn.java:2088)
	at stellar.access.samples.consumer$loading__5569__auto____2873.invoke(consumer.clj:1)
	at stellar.access.samples.consumer__init.load(Unknown Source)
	at stellar.access.samples.consumer__init.<clinit>(Unknown Source)
	at java.lang.Class.forName0(java.base@9-internal/Native Method)
	at java.lang.Class.forName(java.base@9-internal/Class.java:378)
	at clojure.lang.RT.classForName(RT.java:2168)
	at clojure.lang.RT.classForName(RT.java:2177)
	at clojure.lang.RT.loadClassForName(RT.java:2196)
	at clojure.lang.RT.load(RT.java:443)
	at clojure.lang.RT.load(RT.java:419)
	at clojure.core$load$fn__5677.invoke(core.clj:5893)
	at clojure.core$load.invokeStatic(core.clj:5892)
	at clojure.core$load.doInvoke(core.clj:5876)
	at clojure.lang.RestFn.invoke(RestFn.java:408)
	at clojure.lang.Var.invoke(Var.java:379)
	at clojure.lang.Util.loadWithClass(Util.java:250)
	at stellar.access.samples.consumer.<clinit>(Unknown Source)
Caused by: java.lang.ClassNotFoundException: clojure.core.reducers.CollFold
	at jdk.internal.loader.BuiltinClassLoader.loadClass(java.base@9-internal/BuiltinClassLoader.java:366)
	at jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(java.base@9-internal/ClassLoaders.java:184)
	at java.lang.ClassLoader.loadClass(java.base@9-internal/ClassLoader.java:419)
	at java.lang.Class.forName0(java.base@9-internal/Native Method)
	at java.lang.Class.forName(java.base@9-internal/Class.java:378)
	at clojure.lang.RT.classForName(RT.java:2168)
	at clojure.lang.RT.classForName(RT.java:2177)
	at uncomplicate.fluokitten.algo__init.__init2(Unknown Source)
	at uncomplicate.fluokitten.algo__init.<clinit>(Unknown Source)
	... 70 more

project.clj :

(defproject stellar/access "0.1.0-SNAPSHOT"
  :description "Panel Data Collection"

  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}

  :dependencies [[org.clojure/clojure "1.8.0"]
                 [org.clojure/core.async "0.3.443"]
                 [org.clojure/algo.monads "0.1.6"]
                 [uncomplicate/fluokitten "0.6.0"]
                 ;--------------------------------Formats
                 [cheshire "5.7.1"]
                 [org.clojure/data.csv "0.1.4"]
                 [semantic-csv "0.2.1-alpha1"]
                 ;--------------------------------Time
                 [clj-time "0.13.0"]
                 [jarohen/chime "0.2.2"]
                 [tick "0.2.4"]
                 ;--------------------------------Technology
                 [com.novemberain/langohr "3.7.0"]
                 [com.novemberain/monger  "3.1.0"]
                 [org.slf4j/slf4j-nop "1.7.12"]    ;) To stop mongo.java logs
                 ;--------------------------------Loggin-and-Profiling
                 [com.taoensso/timbre "4.10.0"]
                 [com.taoensso/tufte "1.1.1"]
                 ;--------------------------------For-Eastwood-Vim-Linter
                 [jonase/eastwood "0.2.4" :exclusions [org.clojure/clojure]]
                 ;--------------------------------For-Fireplace-??
                 [cider/cider-nrepl "0.14.0"]
                 [lein-cljfmt "0.5.6"]
                 ;--------------------------------
                 [danlentz/clj-uuid "0.1.7"]
                 [random-seed "1.0.0"]
                 ]

  :test-paths   ["test"]
  :aliases      {"itest" ["midje" ":filters" "it"]
                 "utest" ["midje" ":filters" "-it"]
                 "test"  ["midje"]}

  :plugins      [[cider/cider-nrepl "0.14.0"]
                 [venantius/ultra "0.5.1"]
                 [jonase/eastwood "0.2.4"]
                 [venantius/yagni "0.1.4"]
                 [lein-cljfmt "0.5.6"]
                 [lein-midje "3.2.1"]]

  :repl-options {:host "0.0.0.0" :port 34567}
  :main nil
  :target-path "target/%s"

  :jvm-opts ["-Xmx2g" "-Xms512m" "-XX:+UseConcMarkSweepGC"]
  :profiles {:uberjar {:aot :all}
             :dev     {:dependencies [[midje "1.8.3"]
                                      [jonase/eastwood "0.2.4" :exclusions [org.clojure/clojure]]]}})

Consider Show protocol

Hey, I really thing it would be valuable to have a Show protocol

consider de following code

(just {:a 2})
;;#<Just uncomplicate.fluokitten.algo.Just@3c6f0c2b>
(show (just {:a 2}))
;;Just {:a 2}

Thanks again!

Enhancement: Consider operadic semantics (convenient composition)

(def curried-add4-a (curry add4)) ;; arity 2
(def curried-add4-b (curry add4)) ;; arity 2
(def curried-add4-c (curry add4)) ;; arity 2
(def curried-add4-d (curried-add4-a curried-add4-b curried-add4-c)) ;; arity 4
(def curried-add4-e (curried-add4-a curried-add4-b 5)) ;; arity 3

A question on fluokitten performance

I followed the instructions in Fast Map and Reduce for Primitive Vectors and Matrices to test the performance of neaderthal and fluokitten. What I found are:

  1. The performance numbers from the neaderthal are close to the post;
  2. Yet, all performance numbers from fluokitten are much worse.

For instance,

(def nx (dv (range n)))
(def ny (dv (range n)))

(defn p+ ^double [^double x ^double y] (+ x y))
(defn p* ^double [^double x ^double y] (* x y))

(with-progress-reporting (quick-bench (foldmap p+ 0.0 p* nx ny)))
;             Execution time mean : 19.735098 ms

Also, the same tests were performed using the current dev version of fluokitten and it also ended up with much slower execution time than what in the post. I wonder what might be causes of such large discrepancies?

It would be great if someone can also conduct similar tests.

Async Monad for Clojurescript?

Fluokitten is really cool! I wanted to start by thanking you for your effort.

Is a port to clojurescript at all possible in the future? The reason I ask is because clojurescript desperately needs an async monad to alleviate callback hell...

`fold` breaks on large vectors?

With version 0.5.1 on clojure version 1.8.0, I encountered this behavior:

(fold (range 99))        => 4851
(fold (range 999))       => 498501
(fold (vec (range 99)))  => 4851
(fold (vec (range 999))) => 0

(fold (vec (range 512))) => 130816
(fold (vec (range 513))) => 0

It seems that fold breaks for vectors with more than 512 elements?

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.