Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
Ralith
Jan 12, 2011

I see a ship in the harbor
I can and shall obey
But if it wasn't for your misfortune
I'd be a heavenly person today

Asymmetrikon posted:

I like Idris over Haskell because of some of the historical weirdness it got rid of (switching : and ::, returning Maybe instead of erroring in, i.e., List access functions, the whole Monad/Applicative thing, Int vs. Integer.) I haven't looked too much into GHC 8, though.
Last I checked Idris's Int was just as wacky as the worst-case of Haskell's, and similarly pervasive.

xtal posted:

I have a bunch of small complaints (Idris improves a lot more than the type system) but the lack of performance (String) and safety (totality) in the Prelude are what gets me. Having an opaque list type already pokes holes in type safety, so at the very least I want a Prelude that is total. Alternatives also tend to be implemented via type classes rather than concrete types which I prefer.
Text is faster than anything Idris has to offer, and [a] certainly isn't opaque! The accessors can be a bit silly, sure, but naive accessors aren't great to use anyway since they don't compose well; use lens!

Adbot
ADBOT LOVES YOU

xtal
Jan 9, 2011

by Fluffdaddy
Sorry for the derail but I am sort of only curious about alternative preludes. It would actually not surprise me if there was one that defined operations in terms of lenses.

Jerry Bindle
May 16, 2003

Barnyard Protein posted:

Does anyone know of a racket function/macro that does something like these clojure operators?

http://clojuredocs.org/clojure.core/-%3E
http://clojuredocs.org/clojure.core/-%3E%3E

...

Update: I've finally learned enough racket to be able to write the macro without thinking about it to hard.. Then I remembered I posted here about it, posting in case someone else is interested. Racket is cool.

(I used the thread-last operator from clojure as to implement thread first, forgot which was which)

Lisp code:
(define-syntax ->>
  (lambda (stx)
    (syntax-case stx ()
      [(->> o p0)
       (let ([p0-proc (car (syntax->datum #'p0))]
             [p0-args (cdr (syntax->datum #'p0))]
             [init  (syntax->datum #'o)])
         #`(#,p0-proc #,init #,@p0-args))]
      [(->> o p0 p1 ...)
       #'(->> (->> o p0) p1 ...)])))
Usage example,

Lisp code:
(syntax->datum (expand-only #'(->> 'A (list 'B 'C) (list 'D 'E) (list 'F 'G)) (list #'->>)))
yields,

Lisp code:
'(list (list (list 'A 'B 'C) 'D 'E) 'F 'G)

xtal
Jan 9, 2011

by Fluffdaddy

Ralith posted:



Text is faster than anything Idris has to offer, and [a] certainly isn't opaque! The accessors can be a bit silly, sure, but naive accessors aren't great to use anyway since they don't compose well; use lens!

I just wanted you to know I am really on board with lenses now. I was avoiding them because I think Template Haskell is the plague but I'm able to compartmentalize all of that junk in a Types file.

Ralith
Jan 12, 2011

I see a ship in the harbor
I can and shall obey
But if it wasn't for your misfortune
I'd be a heavenly person today

xtal posted:

I just wanted you to know I am really on board with lenses now. I was avoiding them because I think Template Haskell is the plague but I'm able to compartmentalize all of that junk in a Types file.
:shobon:
You don't actually need to use Template Haskell to use lenses at all, even advanced things like biplate; the boilerplate is concise and linear wrt. your original code. The TH just saves a few lines and ensures consistency, which is enough reason for me to use it, but it's by no means unavoidable. One of the original design goals of lens was actually to allow people to easily make libraries compatible with it without even depending on the package.

xtal
Jan 9, 2011

by Fluffdaddy

Ralith posted:

:shobon:
You don't actually need to use Template Haskell to use lenses at all, even advanced things like biplate; the boilerplate is concise and linear wrt. your original code. The TH just saves a few lines and ensures consistency, which is enough reason for me to use it, but it's by no means unavoidable. One of the original design goals of lens was actually to allow people to easily make libraries compatible with it without even depending on the package.

That's good to know, I was under the wrong impression because the first step in every tutorial is Template Haskell.

VikingofRock
Aug 24, 2008




xtal posted:

That's good to know, I was under the wrong impression because the first step in every tutorial is Template Haskell.

Which tutorials were you using? I've been meaning to try out lenses.

mystes
May 31, 2006

xtal posted:

That's good to know, I was under the wrong impression because the first step in every tutorial is Template Haskell.
That's because the tutorials all start with a bunch of nested record types, and in this case it's convenient to use template haskell to automatically generate the lenses from the record fields. Otherwise the boilerplate code would be pretty verbose and probably immediately cause people to close the tutorial.

xtal
Jan 9, 2011

by Fluffdaddy

mystes posted:

That's because the tutorials all start with a bunch of nested record types, and in this case it's convenient to use template haskell to automatically generate the lenses from the record fields. Otherwise the boilerplate code would be pretty verbose and probably immediately cause people to close the tutorial.

So your choices are the horror of template Haskell or the horrors of boilerplate?

Ralith
Jan 12, 2011

I see a ship in the harbor
I can and shall obey
But if it wasn't for your misfortune
I'd be a heavenly person today

xtal posted:

So your choices are the horror of template Haskell or the horrors of boilerplate?
It takes like 1-2 lines of code to define a basic lens. If a tutorial's about using lenses rather than defining them, it's still best to skip the distraction.

mila kunis
Jun 10, 2011
Picked up the O'Reilly on Elixir and I'm going through it prior to trying out Phoenix. I'm kind of surprised you're allowed to mutate variables though, I thought preventing that was a core thing for functional languages?

Su-Su-Sudoko
Oct 25, 2007

what stands in the way becomes the way

You can rebind variables, but the data itself is immutable.

the talent deficit
Dec 20, 2003

self-deprecation is a very british trait, and problems can arise when the british attempt to do so with a foreign culture





tekz posted:

Picked up the O'Reilly on Elixir and I'm going through it prior to trying out Phoenix. I'm kind of surprised you're allowed to mutate variables though, I thought preventing that was a core thing for functional languages?

elixir (stupidly) has immutable data but mutable references. you can't alter data once assigned to a reference, but you can change what data a reference refers to at any time. all function calls and message sends are pass by value tho, so the damage done in minimal

mila kunis
Jun 10, 2011
Thanks. I've noticed that the O'Reilly examples for simple stuff seems to include a lot of boilerplate. For example, for calculating the product of values in a list, instead of doing something simple like:

code:
  def product(acc \\ 1, [head | tail]) do
    if Enum.empty?(tail) do
      acc * head
    else
      product(acc* head, tail)
    end
  end
they recommend:

code:
  def product(list) do
    product(list, 1)
  end

  def product([], accumulated_product) do
    accumulated_product
  end

  def product([head | tail], accumulated_product) do
    product(tail, head * accumulated_product)
  end
Is their recommended way of doing stuff with using lots of repeated function definitions done for any kind of useful reason?

my homie dhall
Dec 9, 2010

honey, oh please, it's just a machine

tekz posted:

Thanks. I've noticed that the O'Reilly examples for simple stuff seems to include a lot of boilerplate. For example, for calculating the product of values in a list, instead of doing something simple like:

code:

  def product(acc \\ 1, [head | tail]) do
    if Enum.empty?(tail) do
      acc * head
    else
      product(acc* head, tail)
    end
  end

they recommend:

code:

  def product(list) do
    product(list, 1)
  end

  def product([], accumulated_product) do
    accumulated_product
  end

  def product([head | tail], accumulated_product) do
    product(tail, head * accumulated_product)
  end

Is their recommended way of doing stuff with using lots of repeated function definitions done for any kind of useful reason?

It is! Their implementation can run in constant space while yours, potentially, could blow up the stack. Check out the Wikipedia article on Tail Call Recursion/Optimization for more info.

xtal
Jan 9, 2011

by Fluffdaddy

Ploft-shell crab posted:

It is! Their implementation can run in constant space while yours, potentially, could blow up the stack. Check out the Wikipedia article on Tail Call Recursion/Optimization for more info.

His implementation is still TCO, it just uses an if statement rather than patterns and guards. The comparison remains linear time (pattern matching can only sometimes be optimized to constant; guards never can.)

This is a matter of preference but functional programmers consider if statements to be ugly and imperative.

xtal fucked around with this message at 23:27 on Oct 10, 2016

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

the talent deficit posted:

elixir (stupidly) has immutable data but mutable references. you can't alter data once assigned to a reference, but you can change what data a reference refers to at any time. all function calls and message sends are pass by value tho, so the damage done in minimal

Local mutation has basically none of the disadvantages of shared/global mutation and eliminates a lot of local data-flow headaches. You should not feel bad about using it.

the talent deficit
Dec 20, 2003

self-deprecation is a very british trait, and problems can arise when the british attempt to do so with a foreign culture





rjmccall posted:

Local mutation has basically none of the disadvantages of shared/global mutation and eliminates a lot of local data-flow headaches. You should not feel bad about using it.

i get why they chose to allow rebinding references but it makes it significantly harder to catch errors when your primary flow control involves pattern matching (which uses unification not equality)

sarehu
Apr 20, 2007

(call/cc call/cc)

rjmccall posted:

Local mutation has basically none of the disadvantages of shared/global mutation and eliminates a lot of local data-flow headaches. You should not feel bad about using it.

Yeah, the main benefit of functional programming is in having immutable data structures (that can be efficiently used). You can connect them together and use them more versatilely than otherwise, and are harder to screw up. It's generally a good style of software architecture.

A rather nice pure functional programming language would be a version of Rust without RefCell, Cell, or other stuff that uses UnsafeCell, that lets you freeze objects onto a garbage collected heap. So you get local mutation and build arrays and can do mutable borrows. But it would also benefit from not having horrendous "let mut _:_" bullogna and also some goto statements to scare off undesirables.

xtal
Jan 9, 2011

by Fluffdaddy
Is local mutation necessary with sufficiently advanced COW and GC? You don't need to bust out transients in Clojure often and I don't think Haskell even includes them. I don't think the real world performance improvement is big enough to involve mutable state; and, if you spent the time improving the implementation of your immutable structures instead, its benefits would apply to all your code implicitly.

sarehu
Apr 20, 2007

(call/cc call/cc)

xtal posted:

Is local mutation necessary with sufficiently advanced COW and GC?

Depends what you're building and how important performance is? And convenience?

When some people got me to do a Goog Code Jam, I first tried using Haskell, and... ick. It's much nicer to develop code rapidly with for loops, with pushing stuff onto vectors, with being able to turn a map into a fold with a variable declaration, and without having to janitor values into and out of functions into the right kind of tuple.

But also imagine doing stuff where performance is important. In C++, people often disable copy constructors on a type for that reason that copies are too expensive, and they don't want to get one accidentally. If you're setting a vector element, it's relatively easy to have an accidental extra pointer to it. I mean, let's say it's in a variable and you're appending to it. v = push(v, x). Well, you'd need some semantic defined there that moves v into the parameter list of push and moves v out without bumping a refcount. That's what Rust has -- only instead of reasoning in your head about what the refcount should be, and hoping the code never evolves into something that has to copy, it's enforced by the language.

sarehu fucked around with this message at 01:45 on Oct 11, 2016

xtal
Jan 9, 2011

by Fluffdaddy
With those criteria I would say that GC and mutability are two sides of one coin. If you're using immutable structures you need good GC. If your performance needs are such that you can't afford immutability, you can't afford a GC either.

sarehu
Apr 20, 2007

(call/cc call/cc)

xtal posted:

With those criteria I would say that GC and mutability are two sides of one coin. If you're using immutable structures you need good GC. If your performance needs are such that you can't afford immutability, you can't afford a GC either.

Not true at all. You can benefit immensely from improving absolute performance. Not all performance requirements are low-latency/low-memory-usage. You also benefit from the convenience of mutable local variables without creeping performance risk.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

xtal posted:

Is local mutation necessary with sufficiently advanced COW and GC? You don't need to bust out transients in Clojure often and I don't think Haskell even includes them. I don't think the real world performance improvement is big enough to involve mutable state; and, if you spent the time improving the implementation of your immutable structures instead, its benefits would apply to all your code implicitly.

I disagree with your premise that the purpose of local mutation is to get better performance. It certainly can give better performance, and it isn't as subject to artificial limits where the sufficiently smart implementation just isn't sufficiently smart enough and you have no choice but to rewrite it all in a completely different style, but I think the real advantage is just the ability to change what value a name is bound to without having to deeply restructure your code around it. I mean, show me a function of any real complexity and I can probably point out several places where the programmer is basically manually performing a rudimentary data-flow analysis that the compiler could easily have done instead, where it would've been much clearer had the code just been able to declare a local variable and change it instead of binding five different names to the "variable" as it evolved during evaluation.

sink
Sep 10, 2005

gerby gerb gerb in my mouf
I don't really find local mutation very useful.

My kind of programming (enterprise SOAy type stuff) doesn't really need super tight performance. GC pauses are occasionally worrisome though.

As for reasoning about complexity: if you honestly think a local mutable variable is going to make your function simpler, then your function is probably too big, or you should just learn how to use fold, map and flatMap (or bind). I can't really see how a local mutable variable makes code simpler. There's something to be said for: maybe that's just how your brain works, and it shouldn't really matter so long as a functional interface is presented upwards. But for devs on my team, I politely decline to merge PRs with mutation unless it's very clearly needed for a very specific reason, and suggest an alternative implementation.

Asymmetrikon
Oct 30, 2009

I believe you're a big dork!
I do like the way Elixir handles local refs - it allows rebinding of names, but the (|>) operator makes it easy to elide names of intermediate forms if you want, so you can just use whichever approach is more appropriate based on the situation. It's kind of annoying that the forms that it allows on the right hand side of the pipe are pretty limited, though (no anonymous functions is the one I really wish it would allow.)

everythingWasBees
Jan 9, 2013




As I'm finding myself using C++ and C# for everything course and research related, I'd really like to try a functional language to give myself a breath of fresh air. I'm mainly interested in making games and interactive graphical toys. Is there a language with more robust Vulkan and OpenGL support than others? Is there any that are more suited than others for games? I know you can use F# with Unity, is that a decent choice?

Ralith
Jan 12, 2011

I see a ship in the harbor
I can and shall obey
But if it wasn't for your misfortune
I'd be a heavenly person today

everythingWasBees posted:

As I'm finding myself using C++ and C# for everything course and research related, I'd really like to try a functional language to give myself a breath of fresh air. I'm mainly interested in making games and interactive graphical toys. Is there a language with more robust Vulkan and OpenGL support than others? Is there any that are more suited than others for games? I know you can use F# with Unity, is that a decent choice?
Are you looking to do low level or high level gamedev? OpenGL (let alone Vulkan) won't come up much in Unity.

netcat
Apr 29, 2008

everythingWasBees posted:

As I'm finding myself using C++ and C# for everything course and research related, I'd really like to try a functional language to give myself a breath of fresh air. I'm mainly interested in making games and interactive graphical toys. Is there a language with more robust Vulkan and OpenGL support than others? Is there any that are more suited than others for games? I know you can use F# with Unity, is that a decent choice?

I don't use unity but since f# gives.you access to everything c# as well you have got good bindings such as opentk or even sfml if you want something more comfortable

leper khan
Dec 28, 2010
Honest to god thinks Half Life 2 is a bad game. But at least he likes Monster Hunter.

everythingWasBees posted:

As I'm finding myself using C++ and C# for everything course and research related, I'd really like to try a functional language to give myself a breath of fresh air. I'm mainly interested in making games and interactive graphical toys. Is there a language with more robust Vulkan and OpenGL support than others? Is there any that are more suited than others for games? I know you can use F# with Unity, is that a decent choice?

Unity will not have the latest version of F#. You're constrained to something about .Net3.5. It's also a bit onerous to set up last time I tried it. It's not a terrible choice.

Su-Su-Sudoko
Oct 25, 2007

what stands in the way becomes the way

leper khan posted:

Unity will not have the latest version of F#. You're constrained to something about .Net3.5. It's also a bit onerous to set up last time I tried it. It's not a terrible choice.

IIRC the latest Unity beta uses .Net 4.6 or something like that
(of course then you're using a beta release, and all the fun that comes with that)

everythingWasBees
Jan 9, 2013




Ralith posted:

Are you looking to do low level or high level gamedev? OpenGL (let alone Vulkan) won't come up much in Unity.

Bit of A, bit of B. If there wasn't good support then I'd just go with Unity in general, as it allows a surprising amount of graphics fuckery if you sidestep a lot of the default systems.


netcat posted:

I don't use unity but since f# gives.you access to everything c# as well you have got good bindings such as opentk or even sfml if you want something more comfortable

This sounds really appealing. F# it is.
Thank you all!

Sinestro
Oct 31, 2010

The perfect day needs the perfect set of wheels.
There's also Vulkan bindings for Haskell and apparently people have done stuff to incorporate post OpenGL 3.0 style code into Haskell too. Vulkan is actually surprisingly nice to use from Haskell because it doesn't have all of the implicit state bullshit that OpenGL has.

VikingofRock
Aug 24, 2008




New version of Elm is out.

Asymmetrikon
Oct 30, 2009

I believe you're a big dork!
Glad they finally got the time-traveling debugger working the way they wanted it to.

Workaday Wizard
Oct 23, 2009

by Pragmatica

VikingofRock posted:

New version of Elm is out.

quote:

Primes — Names like x' are no longer permitted.

but... but... but... I liked my primes :cry:

VikingofRock
Aug 24, 2008




Shinku ABOOKEN posted:

but... but... but... I liked my primes :cry:

Me too! I also liked the [1..5] syntax and back ticks. I suppose I can see the argument for removing all three though.

Arcsech
Aug 5, 2008

VikingofRock posted:

Me too! I also liked the [1..5] syntax and back ticks. I suppose I can see the argument for removing all three though.

The [1..5] syntax was nice, but I'm not too put out by losing it. Backticks I could go either way on, I can definitely see the simplicity of just encouraging |>.

Good riddance to x' style variable names though, they're awful and don't communicate anything meaningful. But then, I also hate point-free style, so I'm somewhat out of step with a lot of Haskellers anyway.

Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy

Arcsech posted:

The [1..5] syntax was nice, but I'm not too put out by losing it. Backticks I could go either way on, I can definitely see the simplicity of just encouraging |>.

They made a pretty big breaking change, though, to encourage use of |>. (x `andThen` y) translates to (andThen x y), but (x |> andThen y) translates to (andThen y x). They had to flip the argument order of andThen to support this change, which I think is pretty bold.

e: luckily the argument types are incompatible, so it's not possible to compile code that was broken this way.

Bognar fucked around with this message at 20:50 on Nov 15, 2016

Adbot
ADBOT LOVES YOU

Asymmetrikon
Oct 30, 2009

I believe you're a big dork!
Making "x |> andThen y" canonical matches with the way all other functions work (the entity they operate on is the last input to the function), so I'm happy about that. I really like the error improvements, especially making type annotations provide more context to errors.

  • Locked thread