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
dirby
Sep 21, 2004


Helping goons with math

gonadic io posted:

Automatic momoization is extremly unintuitive and finicky in haskell. If you need something to memoise, either store it in an explicit list and pass it around, or you have to do the same kind of test as in that post. Or you could just use a library like memo that does it explicitly behind the scenes.
Thanks for this post. Haskell is really intuitive for me to code in for math and it's good to know what it takes to get memoization working right.

Adbot
ADBOT LOVES YOU

dirby
Sep 21, 2004


Helping goons with math

Snak posted:

Totally new to haskell (learning it for a class in school)

It seems pretty cool so far, but I'm stumped on what I thought was a pretty basic operation:

am I barking up the wrong tree here?
Your approach would require building a mapping to ints and this list, neither of which you need. Just cut out the middlemen: you want show Mon = "Monday", etc. so write those...

dirby
Sep 21, 2004


Helping goons with math

Snak posted:

Wait really? I should just make a statement for each possible value of Day? I thought that sounded like poor solution that does not scale well...
If your type has more than, say, ten constructors, then you're probably doing your type wrong. That said, it's certainly possible to use enumerated type stuff to do this, so if you specifically want help doing that, say so, I guess.

dirby fucked around with this message at 01:13 on Sep 17, 2015

dirby
Sep 21, 2004


Helping goons with math

QuantumNinja posted:

Another thing that can help with Haskell is HLint, which will give you suggestions for your code. Vim's Syntastic supports it and certainly made me a better Haskell programmer.
I have a related question, and keep in mind that I don't do a lot of programming. Basically, I loved the HLint-integrated environment that fpcomplete.com had until 2016 when they got rid of it. I would be willing to pay money to get something like it again.

I've never used Vim or Emacs before, is "Vim's Syntastic" the next closest I'd be able to get to that functionality? Looking at YouTube it seems like it's kinda close but would be a pain since I don't already use Vim and its keyboard shortcuts.

dirby
Sep 21, 2004


Helping goons with math

Hughmoris posted:

Poking around Haskell and Functional programming by reading the "Learn You A Haskell" book. In one of the earlier sections, its talking about syntax in functions. It has this example:

code:
lucky :: (Integral a) => a -> String  
lucky 7 = "LUCKY NUMBER SEVEN!"  
lucky x = "Sorry, you're out of luck, pal!" 
If I was describing this function to someone, how would I verbalize that first line? I understand what the function does but I'm not positive what " lucky :: (Integral a) => a -> String" is telling me.

informally: "lucky is a function from Integral things to Strings."
I think this is better: "For each integral type a, there is a corresponding object called lucky which has the type of a function from things of type a to things of type String"

Someone who knows a lot about Haskell/theory can probably phrase it better/correct me.

dirby
Sep 21, 2004


Helping goons with math
I just rewrote a bunch of Mathematica code into Haskell and the compiled Haskell runs significantly slower than the interpreted Mathematica code. I wonder if I'm doing recursion inefficiently or something but my code isn't that complicated so I can't imagine why it would be so slow. https://wiki.haskell.org/Haskell_programming_tips#Avoid_explicit_recursion seems to say I should figure out how to write all my recursive functions as maps and folds and such. Can that really make a significant difference to the runtime? Is there anything else I should be looking out for?

dirby
Sep 21, 2004


Helping goons with math
Thanks for your input everyone. I did some reading and I'm pretty sure I have a guess at what the key thing slowing my program down is. This is a bit simplified from my real code, but it's close. I'm interested in generating a certain Int "f xs" from many small lists of Ints xs, like "f [0,0,0]" up to "f [20,20,20]". This calculation depends on the f values of lists with lower values a lot, and I worry a huge thunk is being generated (am I saying that right?) instead of just using the f-values we calculated previously like my memoizing Mathematica code does.

The key code is roughly something like this (actual code more complicated):

code:
allpairs :: [Int]->[([Int],[Int])]
allpairs xs = ... --almost every nonnegative ([a,b,c],[d,e,f]) pair where [a+d,b+e,c+f]==xs

mexhelper :: [Int]->Int->Int
mexhelper xs int = if int `notElem` xs then int else mexhelper xs (int+1)
minimalexcludant :: [Int]->Int
minimalexcludant xs = mexhelper xs 0

pairf :: ([Int],[Int]) -> Int
pairf (a,b) = xor (f a) (f b)

f :: [Int]->Int
f xs = derivefromlist $ nub $ map pairf $ allpairs xs
I suspect the issue is that when pairf is called, it doesn't immediately use the fact that we should know f a and f b from previous calculations, and instead we end up calculating a big tree of lists that sum to lists that sum to...before anything gets evaluated. I think the key to fixing this is to rewrite the recursion that makes f work (with foldl'?), but I'm not certain how to go about it.

dirby fucked around with this message at 12:57 on Apr 11, 2016

dirby
Sep 21, 2004


Helping goons with math
After reading a lot about strict vs. lazy and seq and bang patterns and a bunch of other stuff, I just mimicked the explicit memoization outlined in https://wiki.haskell.org/Memoization#Memoization_with_recursion and made no other changes finally got reasonable speed very comparable speeds (maybe half the speed?) to what I was getting with my memoized Mathematica code. That's much more workable than the "slowfib" style calculation is seemingly impossible speed I had been getting before.

dirby
Sep 21, 2004


Helping goons with math

gonadic io posted:

although honestly given that the chunksOf 2 is hard-coded to be 2 I recommend getting it to just return a pair. Lists with statically-known lengths are a code smell.

chunksOf 2 returns a list of lists of length 2 except maybe there could be a list of length 1 at the end if you didn't statically know that the argument had even length. Therefore, the best you could do is make it into a function that returns a list of pairs and does something counterintuitive at the end for odd-length inputs.

Adbot
ADBOT LOVES YOU

dirby
Sep 21, 2004


Helping goons with math

205b posted:

I did need a distinct value for each node, but it turned out I could get away with a singly-linked tree, so I went with that. Just trying to wrap my head around what I did wrong. I think I get it now! What you're saying is that let x = 0:y; y = 1:x in x doesn't give you two nodes pointing at each other, but a chain of infinitely many nodes.

As a followup, how come length (let x = 0:y; y = 1:x in x) pegs my processor but my original example just sat there doing nothing?

Contrast the following two pieces of code.

x = 0:y; y = 1:x; main = print $ take 5 x outputs [0,1,0,1,0]. For the purpose of answering your question, you can safely pretend that it: looks at the first entry of x and sees it's known to be 0. Then it looks for the second entry of x, which is defined to be the first entry of y, which is known to be 1. Then it looks at the next entry of x, which is the second entry of y, which is the first entry of x, known to be 0...fourth must be 1...fifth must be 0, and we're done.

Since that doesn't ask the computer to do anything infinite, there's no problem with the theoretically-infinite definition of x.


But change main to print $ length x and it would have to do something along the lines of: Check if x has a first entry. It does, so the length is at least 1. The next entry, if any, would be the first entry of y, which exists (it's 1), so the length is at least 2. The next entry, if any would be the first element of x again (by the definition of y), so the length is at least 3...at least 4...5...6...7... and it would never stop.

  • Locked thread