These are chat archives for evhub/coconut

15th
Mar 2017
Julian Ospald
@hasufell
Mar 15 2017 19:47
(0.5, 0.7) |*> (+) works... 0.5 |> (+ 1) doesn't
Julian Ospald
@hasufell
Mar 15 2017 19:59
also, where are functors? No libraries?
yggdr
@yggdr
Mar 15 2017 20:11
@hasufell .5 |> (+)$(1). (+) captures the + operator as a function. The $ means auto-curry'ing, and then call the function with one argument of value 1, yielding what you wrote as (+ 1)
Julian Ospald
@hasufell
Mar 15 2017 20:12
that is odd
yggdr
@yggdr
Mar 15 2017 20:13
I'm still not sure myself that I like the syntax, but maybe I just need to actually write code in it to make up my mind
Julian Ospald
@hasufell
Mar 15 2017 20:13
from a functional standpoint +1 makes perfect sense
(+)$(1) is tackling details of the implementation
Evan Hubinger
@evhub
Mar 15 2017 20:25
@hasufell I agree that +1 looks nicer, but since Coconut is a strict superset of Python, that syntax is off-limits, since +1 is valid Python syntax for positive one. @yggdr is correct that the right way to do it would be (+)$(1). As for libraries, you have all of Python at your disposal, since Coconut compiles to Python any Python library is usable from Coconut.
Julian Ospald
@hasufell
Mar 15 2017 20:26
how would a python library implement Monads with infix bind operator?
Evan Hubinger
@evhub
Mar 15 2017 20:29
@hasufell You would just have a function called bind then call it using Coconut's infix notation as a `bind` b. You could use PyMonad from Coconut if you wanted, for example. Another alternative to +1 that you can use, by the way, would be (-> _ + 1), using implicit lambda syntax, if you think that looks nicer.
Julian Ospald
@hasufell
Mar 15 2017 20:36
Can I not define my own operators?
Eric Anderson
@Nexus6
Mar 15 2017 20:53
@hasufell Would overriding Python's magic methods on classes suit your purposes? Something like MyClass.rshift() meaning 'bind' for example, which would allow for a syntax like a >> b where a is a MyClass and b a function?
Julian Ospald
@hasufell
Mar 15 2017 20:54
uh, that sounds like dangerous meta-programming
Eric Anderson
@Nexus6
Mar 15 2017 21:16
Danger is subjective. :-) Actually Python makes these operators available as functions on classes so that you can do just this kind of thing. Someone who knows Python better than I do please correct me (@evhub), but I don't think that Python has any way of defining free functions (meaning those not defined in a class) that can override symbolic operators. I think that you're stuck with the symbolic operators whose functions are baked-in to object, namely http://www.python-course.eu/python3_magic_methods.php and overriding those is the only solution if you want to customize operators.
Julian Ospald
@hasufell
Mar 15 2017 21:17
Then that sounds like a thing coconut should allow
the compiled python code doesn't need to have those operators anymore
Eric Anderson
@Nexus6
Mar 15 2017 21:33
As a transpiler, I'm not sure if that would be possible with Coconut as it stands. The compiler spits out pure Python so if something can't be done in Python Coconut won't be able to do it either. I agree that it would be very cool for Coconut to have language elements that can't be expressed at all in pure Python, but (I speculate) to do that might require dealing with the AST directly and compiling not to Python but to .pyc. I'd be curious to hear @evhub 's take on that -- how much work it would be and how much compatibility ("all Python is Coconut") would be at risk.
Eric Anderson
@Nexus6
Mar 15 2017 21:38
An example of a compile-to-Python language that went this route is Mochi: https://github.com/i2y/mochi . It seems to be abandonware now unfortunately.
Julian Ospald
@hasufell
Mar 15 2017 21:49
Well, I feel otherwise coconut is just a lot of "syntax sugar" if it doesn't go this route, is it? I don't see how "all Python is Coconut" would be at risk here. The translation might just be non-trivially more difficult.
Eric Anderson
@Nexus6
Mar 15 2017 22:37
It is a big lump of sweet sugar, to be sure, but so are all of the other transpilers out there. Scala.js and ClosureScript and Elm are just sugar on top of JavaScript. Those languages don't make claims like "all JavaScript code is Scala.js code" however. As you say a lot of things might be "doable but non-trivial" if Python source code compatibility is to be maintained. Changing the compatibility to be at the bytecode level and not the source level might open up a lot of new possibilities to grow the language in different directions. Doing so might run counter to one of the goals of the project however, which is, if I understand correctly, to make FP more accessible to Python programmers (via all the sugar) while not requiring developers to go "all in" with the new language.
Julian Ospald
@hasufell
Mar 15 2017 22:38
Elm is not just sugar
but it probably depend on the definition there
Eric Anderson
@Nexus6
Mar 15 2017 22:38
Really? Shows how much I know about it - haven't had time to play with it yet and I have an aversion to JS. :-)
Julian Ospald
@hasufell
Mar 15 2017 22:40
Elm doesn't depend on js notation or features that closely that you could argue it's "sugar". It's pretty independent and I'd argue adding another output-language wouldn't be that much of work.
Same for purescript
Pretty sure they were built that way: 1. design the language from the ground up 2. figure out how to compile to js
not mixing those steps
Julian Ospald
@hasufell
Mar 15 2017 22:47
that ofc also limits the ways you can just throw in javscript code: you can't. Maybe there's some templating to do inline-js, but other than that, probably not
Evan Hubinger
@evhub
Mar 15 2017 22:50
@hasufell @Nexus6 Allowing the definition of new operators is actually pretty trivial, but as I see it there are two major downsides, which is why I didn't do it:
  1. if your library was imported from Python, those operators would no longer be accessible, which seriously hurts the ability to distribute compiled Coconut, and
  2. code readability can be significantly harmed by allowing the definition of custom operators, since it means that the standard vocabulary of the language becomes insufficient to understand an arbitrary piece of code.
Julian Ospald
@hasufell
Mar 15 2017 22:51
I disagree on 2., but I see what you mean with 1. However, I wasn't even sure if people want to distribute coconut-written code as pure python libraries
I'd rather want to do the opposite: distribute coconut libraries
Evan Hubinger
@evhub
Mar 15 2017 22:57
@hasufell One of the big benefits of Coconut is how easy it is to distribute as if it were written in Python (with the added bonus that you can even distribute it on any Python version), and maintaining that is definitely something I would like to do. Since Coconut is a small language, trying to rely only on other libraries written in Coconut would seriously hamper Coconut's ability to grow. Instead, by masquerading as Python, Coconut is able to be a lot more practically useful in the existing ecosystem.
Julian Ospald
@hasufell
Mar 15 2017 22:58
In my opinion, that's what limits the language to be truly functional
Eric Anderson
@Nexus6
Mar 15 2017 22:58
"Distribute" in the Python world usually means putting your code on pypi and I don't know how that would work with .coco sources. I've just compiled to .py and put that out on pypi - no coconut sources involved.
Julian Ospald
@hasufell
Mar 15 2017 23:00
But I understand this is a design decision and not a trivial one
Evan Hubinger
@evhub
Mar 15 2017 23:00
Coconut is not, and was never intended to be, a purely functional language like Haskell or ML--Haskell and ML already exist, so why would anyone use Coconut in that world? Instead, Coconut's purpose is to allow the most powerful idioms of those languages to be used with Python (many of which, like pattern-matching and tail call optimization, are very non-trivial to implement in Python by hand).
Julian Ospald
@hasufell
Mar 15 2017 23:02
the most powerful idiom of haskell is purity though ;)
for pattern matching there are even some odd ADT libraries I've seen, but ofc not very clean solutions
The main thing I am annoyed by when doing python stuff is caring about random things like "oh, is this object None" or "oh, is this list empty?" etc... where stuff like Functors (as in fmap) would allow me to easily just chain together something
without writing explicit checks and whatever for everything
when you have a random library providing those things, it still feels alien, because you miss the operators, syntax etc to make it really useful
Evan Hubinger
@evhub
Mar 15 2017 23:07
I would argue that in most cases Coconut's map is sufficient for most purposes like that--can you give me a specific example?
Eric Anderson
@Nexus6
Mar 15 2017 23:08
For the sake of discussion, I'm curious, how contrary would it be to the "mission" of Coconut to go the compile-to-bytecode route, which would (I think) allow full Python interoperability (no need to leave the library ecosystem behind) while allowing the break from Python source compatibility. Basically, do what Mochi did. Distribution would be one problem, I'm not sure you can use Pypi for distributing bytecode.
Julian Ospald
@hasufell
Mar 15 2017 23:09
well, map works only on collections or how does it work?
Evan Hubinger
@evhub
Mar 15 2017 23:09
@Nexus6 Distribution is definitely a problem, as is the fact that doing that weds Coconut to CPython, since other Python implementations (e.g. PyPy) don't use the same sort of bytecode.
Eric Anderson
@Nexus6
Mar 15 2017 23:10
I did not know that about the runtimes. Are there bytecode differences between 2.x and 3.x as well?
Evan Hubinger
@evhub
Mar 15 2017 23:10
@Nexus6 Yes, there are bytecode differences between versions, although theoretically Coconut could compile to either, though it would make compiling to something universal impossible.
@hasufell map(func, iterable) returns an iterator where func is applied to every element of iterable
Julian Ospald
@hasufell
Mar 15 2017 23:11
then it's more of a Traversable, not a Functor
for example, I have some xml parsing which can in very deep nesting return a list that contains an empty list, then a non-empty list containing None object etc etc
figuring out every case there and doing explicit checks is annoying
where you could just fmap over everything
Julian Ospald
@hasufell
Mar 15 2017 23:16
or even fold
Evan Hubinger
@evhub
Mar 15 2017 23:17
My understanding is that fmap says "return something of the same type with this function mapped over the contents", while map says "regardless of what type you give me, return an iterator over the contents of the thing with this function mapped over it". If you want to get back to the fmap behaviour, you can just call list on the resulting iterator, although then you lose the performance benefits of keeping everything lazy until absolutely necessary (which, of course, you get automatically in a purely functional language like Haskell, but you don't in Python). As for fold, Coconut's reduce is exactly the same thing.
Julian Ospald
@hasufell
Mar 15 2017 23:21
fmap is something which is unrelated to collections, it can potentially work on any parametrized data type
Evan Hubinger
@evhub
Mar 15 2017 23:24
Yes, I agree, though in Coconut, every parameterized data type (if you create it using data) behaves like a collection. This is all very abstract--if you give me an example of a problem you're trying to solve or some functional code you'd like me to translate, I'd love to show you how it all fits together.
Julian Ospald
@hasufell
Mar 15 2017 23:25
data Nothing()
data Just(n)
Maybe = (Nothing, Just)

fmap((*2), Just(3)) # should yield (Just(6))
fmap((*2), Nothing) # should yield (Nothing)
Evan Hubinger
@evhub
Mar 15 2017 23:27
Here's from the Coconut console:
>>> data Nothing()
>>> data Just(n)
>>> Tree = (Nothing, Just)
>>> Just(3) |> map$(-> _*2) |*> Just
Just(n=6)
>>> Nothing() |> map$(-> _*2) |*> Nothing
Nothing()
As you can see, the difference between map and fmap is exactly as I was saying--fmap preserves the type of the object, whereas map does not. Honestly, if you wanted a function that behaves like fmap, I could add it to Coconut pretty easily.
Julian Ospald
@hasufell
Mar 15 2017 23:29
ah you mean fmap is an endofunctor and map isn't (necessarily)
Evan Hubinger
@evhub
Mar 15 2017 23:30
Yeah, that's right.
Here's my quick-and-dirty implementation of fmap in Coconut:
def fmap(func, obj) =
    obj |> map$(func) |*> obj.__class__
Julian Ospald
@hasufell
Mar 15 2017 23:31
then it should actually be trivial to write an fmap yeah
nice
I have to go to sleep, I'll catch up tomorrow
Evan Hubinger
@evhub
Mar 15 2017 23:33
See ya! I'm going to raise an issue to add fmap to Coconut's built-ins. I'm not sure what I'm going to do about it yet, but it deserves an issue, for sure.
The issue is #237.
Julian Ospald
@hasufell
Mar 15 2017 23:36
wait, so map is structure-preserving for lists, but not for ADTs?
Evan Hubinger
@evhub
Mar 15 2017 23:38
@hasufell In Python, it depends on your version. In Coconut, map is never structure-preserving. It always returns an object of type map, which supports all the basic iteration primitives (indexing, looping, reversing, etc.), but nothing else.
Julian Ospald
@hasufell
Mar 15 2017 23:39
yeah, I heard they changed the behavior of map for python3
anyway, off I go, laters
Evan Hubinger
@evhub
Mar 15 2017 23:39
Yes. Coconut standardizes one implementation across versions, however. See ya!
@Nexus6 Following up on the bytecode thing, that was something I considered and decided against pretty early on, simply because of the portability concerns. CPython bytecode is linked completely to the specific CPython version, and of course to CPython itself. Python source, on the other hand, has the ability to be completely unlinked from any version or implementation--and you can always compile Python source down to CPython bytecode if you want, anyway.
Eric Anderson
@Nexus6
Mar 15 2017 23:49
I didn't know about the bytecode-level incompatibilities. I was mainly bluesky-thinking about how Coconut might be open to growth in various new directions if the constraints of the intermediate Python representation were dropped. I was thinking that compile-to-pyc would allow a developer to hold on to the Python library ecosystem while getting new Coconut language features that weren't even expressible in pure Python.
I'm not sure if that last part even makes sense, not sure if there's anything that you could express in bytecode that you couldn't express in Python itself.
Eric Anderson
@Nexus6
Mar 15 2017 23:55
In the JVM world, there are things such as mix-ins that Java doesn't support that Scala does support. So clearly the VM can do things that the Java language can't, and I thought that perhaps the same might be true of Python.
Evan Hubinger
@evhub
Mar 15 2017 23:56
@Nexus6 There's nothing I know of that you could do in Python bytecode that you couldn't do in Python source. My understanding of the reason Mochi decided to compile to bytecode is just because their language is so different from Python that trying to compile to a high-level Python representation would be harder than trying to compile to a low-level bytecode representation.