« first day (4064 days earlier)      last day (795 days later) » 

12:14 AM
Aight, so is there someone here who can learn us a Haskell for great good?
If not, I can teach BitCycle or tinylisp.
Perhaps @WheatWizard?
When is LYAL?
Now as soon as we decide on a language
Do you know enough Haskell to give a basic introduction to the language?
12:32 AM
@DLosc a little bit, but only in the repl
@Nitrodon judging by the clock, I'd say now o'clock
I have yet to create any "real" programs in Haskell.
i have the strangest feeling that this exact conversation has happened twice before
@UnrelatedString Do you volunteer as tribute? :P I see you've written some Haskell answers.
12:43 AM
probably going to hit the gym in like 15 minutes but i could try to kick things off before then
i'm also actually terrible at haskell but my grasp on the basics is strong enough
The only time I've ever used Haskell is to try and find holes in RTO's security
(Don't worry, I failed)
the stuff i'm bad at usually isn't relevant to golf so guess i'll look at some previous lyals to see how it makes sense to start off
Cool cool
@UnrelatedString i think u should start with what haskell actually is (what type of programming language is it, what makes it unique)
Welcome to the fifteenth Learn You A Lang for Great Good! Today, we'll be learning Haskell, a polymorphically statically typed, lazy, purely functional language. During the event, feel free to post CMCs to practice Haskell, ask questions about the language, and so on.
12:49 AM
haskell is uhh
purely functional, statically typed, lazily evaluated, and very cool™
ok dont know what half of that means but thats very cool
@AidenChow See also
@RadvylfPrograms ^^^^ Pin plz
to start things off it's one of the few languages that has syntax for anonymous functions where it's not golfier to submit them, so a function definition is written as so:
add x y = x + y
this is a terrible example, which i have chosen for several reasons
note that the left hand side represents the syntax with which you would call add, i.e. to add 1 and 2 you would use add 1 2
Q: Implement a very simple ALU using only NAND gates

PyautoguiNote: This challenge was inspired by Joe Z's many excellent questions surrounding NAND golfing. Description Your goal in this challenge, should you choose to accept it, is to implement a very simple ALU using just NAND gates. The ALU can only perform the the following four operations: 00, meanin...

12:55 AM
which is equivalent to (add 1) 2, because function application is effectively an operator (and specifically the operator with the tightest precedence)
@UnrelatedString what, could you explain what (add 1) 2 means in layman terms, i dont really get that
isnt add taking two arguments, why its one over here
functions are by default curried: add has type (Num a) => a -> a -> a, and don't worry about the (Num a) => bit for now but this means that add 1 is also a function (Num a) => a -> a that takes some number and increments it
what is curried function
im a bit of a noob at programming as you can tell
and what makes that example terrible is that there's a much, much shorter way to do the exact same thing:
add = (+)
1:01 AM
@AidenChow Basically it means that instead of passing multiple arguments to a function, you pass them one at a time. See also Wikipedia.
since functions are simply values
A curried function means that (+) is a function that takes one variable and returns a function which takes another variable.
My main Haskell question is: Say I write a function that returns an integer (or list of integers, or whatever). How do I write a main program that calls the function and outputs the result?
so add 3 (or (3+)) is a function that adds 3 to its input.
full prgrams in haskell define a value main :: IO ()
so to print the result of a function call you would most likely use print :: (Show a) => a -> IO ()
1:03 AM
@UnrelatedString so all of that stuff isnt counted in the byte count right
Q: Complex permutation

Felipe SoaresGiven an array of integers as input(including negative integers), find all unique permutations that do not have the same number next to each other, then print them all out. If no permutations were found, print Nothing or return an empty list or any consistent output indicating that none were foun...

@UnrelatedString Is $ function composition?
$ is defined as f $ x = f x. Its main use is that it binds last.
1:05 AM
welp gtg
@DLosc it's application with different precedence
print $ f 88 means the same thing as print (f 88), but doesn't require parens.
how to print multiple times in the same code, i try main=print (...) on the second line, it dont work
do is the "normal" syntax for binding two IO functions.
or you can use >>, which do is just syntactic sugar for in this case
@Nitrodon yeah, noob at programming here, i have no idea what that means
how to use that
1:08 AM
ok thank you
@Nitrodon Okay, that's interesting. So (in C terms) $ is lower-precedence than the default implicit application operator
@AidenChow Don't worry, Haskell terminology is famously confusing even to experienced programmers of other languages. That's why I've been looking forward to having someone to teach it.
Implicit application operator has precedence 11 (or 12?, which is the highest possible). $ has precedence 0 (lowest possible).
1:10 AM
what does "binding" mean in this context?
I just meant precedence
Is it also right associative?
I really should know, but I'm rusty.
Yes, f$g$x is f (g x)
while f g x is (f g) x
@UnrelatedString wait what does that mean?
1:13 AM
@Bubbler Would it be fair to say then that $ is essentially like an open parenthesis that autocloses at the end of the expression?
I’m having a hard time parsing English today
yeah, that's accurate
I guess you can think of it like that
@user Rephrased: Haskell has anonymous functions, but the syntax isn't very golfy, so you'll usually see named functions in code golf instead.
I thought they were just \x->fda go jh or something
1:15 AM
\x y->whatever is kinda golfy but is equal in length with f x y=whatever and loses to x!y=whatever (infix binary definition)
and it sometimes loses to point-free definitions
and also loses badly when you want to use guards
You can use guards in lambdas?
okok slow down: what is infix binary definition, point-free definition, and guards??
or pattern matching, I guess
1:18 AM
also how do you call the function \x y->whatever, with f??
Infix binary definition: you can use symbols as names, which is then parsed as a binary operator like + in a + b. You can use any symbol that is not already defined, so common symbols used are !, #, ? iirc
\x y->whatever is an anonymous lambda like Python's lambda x,y:whatever or JS's (x,y)=>whatever. You can give it a name like f=\x y->whatever and then use f to call it.
@Bubbler so that can only be used when there is 2 arguments?
Two or more arguments.
1:23 AM
@Bubbler could you give example for more than two arguments
f x y z=... can be defined as (x!y)z=... and it saves a byte
Pointfree: Using various techniques, a function can often be written in a way that does not name the arguments at all.
In the simplest form, f x y=x+y can be transformed to f=(+).
More sophisticated transforms are possible but learning how to do it requires some understanding of lambda calculus and combinatory logic, so as a beginner you can just remember the site pointfree.io that does the transformation for you. (Note that it doesn't guarantee an optimal transformation.)
Pointfree form has the additional advantage in golf in that, like an anonymous lambda, you don't need to count leading f= in the score.
For those of us who know a little combinatory logic, what are the main combinators in Haskell? I remember seeing flip in some answers--I assume that reverses the order of arguments. And I think . is composition, right?
Yes, flip and . are the most common building blocks, followed by >>=, =<<, and <*> when you need to reference an argument multiple times.
I always forget what the three exactly do on functions though...
was >>= the one that acts like the S combinator on functions?
what are some simple challenges for us new to haskell that we can do
1:35 AM
All three are some variations of S
S is the one that does S(f, g, x) => f(x, g(x)), right?
what are combinators, and how are they used in code?
@AidenChow HMC: Given a nonnegative integer, return its factorial.
uhhh, is there recursion in haskell
how to do conditionals in haskell
1:43 AM
Conditional: if cond then x else y
if, then, else are keywords
ok thanks
cond must be of type Boolean (no implicit coersion or truthy/falsy) and x and y must have the same type.
Recursion: Name the function f and use the same name f in the body. That's it.
@Bubbler is the condition similar to python conditions (like == for equals)
@Bubbler Looks like maybe >>= takes the one-argument function on the left and =<< takes it on the right. Not sure yet what the difference is between =<< and <*>.
@AidenChow Nice ^_^
@AidenChow Comparison operators are mostly the same but you use /= instead of !=.
1:49 AM
Now here's one cool thing about Haskell: You can write multiple definitions for the same function, and it'll use the first definition that works for the arguments you passed. Try it online!
@DLosc oh, huh thats cool
Many languages have that.
Typescript and elixir for starters
@emanresuA i have no idea what languages those are but thats pretty nice
certainly wish desmos would have something like that -_-
And it's also a nice task to introduce guards. The "multiple definition" way only works by pattern matching (e.g. it can only test for equality for integers), but guards can have arbitrary boolean condition. Try it online!
The syntax is f args | cond1 = body1 | cond2 = body2 | ...
@AidenChow Desmos isn't meant to be a programming language
1:54 AM
@Bubbler do you always have to put otherwise for the last statement or is there some golfy way to do that
@emanresuA I'm mostly familiar with it from Prolog. (I guess function overloading in C and related languages is kinda similar, but not really useful in the same way.)
For the last guard, using otherwise is recommended in production, but it's just an alternative name for True, and it can be further golfed to 1>0.
@emanresuA Doesn't mean it can't have nice features... Besides, this is very related to piecewise functions, which are important in math.
So the golfed code would be f x|x>0=x*f(x-1)|1>0=1.
is there a builtin function of some sort for factorials, or do you have to implement it by urself
1:57 AM
@DLosc I guess, yeah.
Factorial is not a built-in, but it is actually as simple as f x=product[1..x]
[a..b] is range syntax that creates a list of numbers from a to b inclusive, and product is a built-in that multiplies all numbers in the given list.
The full list of functions available without imports can be found here
@Bubbler dang, that is quite a lot
Yeah, and it's loaded with math terms too
what, how can there be infinite lists
Haskell is lazy.
2:03 AM
You define an infinite list, and Haskell only actually computes what is actually needed from that list
and the definition of infinite list can also be recursive, which gives some advantage in certain sequence challenges
Also a "canonical" example of defining Fibonacci as a recursive infinite list
Basically it defines the sequence using the initial terms and the recurrence relation
@Bubbler drop 1 is just tail, right?
I forgor most of Haskell prelude lol
HMQ: Given a list of integers with at least two elements, add the first two elements together and put them back in the list. For example, [2,3,4,10] -> [5,4,10].
2:09 AM
... that would require some introduction to pattern matching with lists
Indeed ^_^
Basically a list in Haskell is a linked list, constructed using "nil" [] and "cons" :
The first item of a list is called head, and the rest is called tail (which are also the names for the built-in functions)
[2,3,4,10] is actually 2:3:4:10:[] (and I remember a PPCG challenge which had you "desugar" strings similarly)
A common technique to calculate something on lists is to pattern match on it.
You can divide the input into two cases: either the input is empty, or it is not empty.
@DLosc Something like head x + head tail x : drop 2 x?
2:14 AM
And when it is not empty, you can extract its head and tail immediately like this:
@Bubbler or some ugly tail calls (fet it? Heh)
@emanresuA You want head instead of fst, I just made that mistake myself
f [] = something
f (h:t) = another thing
fst takes a pair
For example, a built-in function product (returning 1 for empty) can be defined as
2:15 AM
@Bubbler So, destructuring?
product [] = 1
product (h:t) = h * product t
Almost got it. head tail x tries to apply the head function to the tail function, which doesn't make sense and is a compile-time error.
head $ tail x then?
no, because $ has lower precedence than :
head (tail x)
Use parens first, and then try to eliminate parens when possible
2:16 AM
It's a bit disappointing that head.tail x has the wrong precedence too
Hm, I just discovered the !! operator, though... that saves some bytes over head
lol mightve overcomplicated it a bit idk
was looking through the documentation for stuff i could use
f(a:b:c)=a+b:c ?
And the pattern matching can go further, like if you want to match first two elements and the rest, you can pattern match (h1:h2:t)
Yeah, you got it already
2:21 AM
@AidenChow Haha, nice! X^D That idiom for "all but the first two list elements" is very Desmos.
Yeah lol
@emanresuA its that simple????
@DLosc That'd be f(A)=A[3...A.length] in desmos right?
(\x->l!!x) can be shortened to (l!!) too
@emanresuA yeah
it could be even shorter like A[3...]
2:24 AM
@AidenChow In Haskell, this is drop 2 A (that is, get rid of the first two elements of A and return the rest)
@Bubbler As expected, golfed by xnor
yeah, do is pretty unintuitive when not used in the usual context.
@DLosc it is useful to think of it as an infix function since you can use it for things like map($1)[succ,id,(*2)] to apply each of [succ,id,(*2)] to 1
also ($) is actually sort of a specialization of id
What is Haskell's comment syntax?
2:31 AM
In that golfed version, what does do b:c:d<-[t] do when t=[]?
-- for single line
{- ... -} for multiline iirc
@Nitrodon fail
and multiline comment can be nested
That's good
@Nitrodon what does it even do when t is anything???
like just explain what that code is supposed to do, thanks
@UnrelatedString but there's no error when the entire function is called on a 1- or 2-element list
2:32 AM
lists are a MonadFail iirc so if a pattern match in do-notation fails it just goes to the defined failure value of []
instead of erroring
Iterate over single-item list [t], filter the elements that match the pattern b:c:d, and flat-map using the next expression
That's how list monad works
think of it like prolog because as we all know prolog is the most intuitive language in existence
do x<-foo; bar x is equivalent to foo >>= bar, where >>= translates to flat-map for the list monad.
i actually like prolog
I had an x there, so foo >>= (\x -> bar x)
2:36 AM
Right, I just realized
do syntax is more "natural" with monads like IO, where it basically acts like an imperative sequence of instructions.
but since it's just syntactic sugar, it works for all monads
@AidenChow See, now we've gotten into the part where I'm completely lost ;)
What is MonadFail anyway?
ok so can someone explain what do does exactly, cant make any sense of what yall are saying
2:41 AM
since lists are lazy you can basically just use the list monad to write backtracking algorithms
do is a bit hard to explain in full generality.
It pretty much requires you to understand what a monad is.
@Nitrodon a what?
HMQ: Given a row of Pascal's triangle, generate the next row of the triangle.
2:43 AM
so do is higher level stuff right
For now, just treat do as something you can use to do multiple things in your main function.
do in the IO monad is normal stuff. do in an arbitrary monad is unintuitive.
how to add corresponding elements in two equal length lists
2:48 AM
I can try to explain monads if you want. Do you know what a functor is?
@UnrelatedString ok thanks, i just put the two lists as arguments after it right
not as good as other peoples', but heres my attempt: tio.run/##y0gszk7Nyfn/…
@UnrelatedString I've also got a 27-byte pointfree version, but it doesn't parse if I put the function name in the header.
Oh--I need that -cpp flag?
2:52 AM
it just slaps the c preprocessor on iirc lmao
is there a short way to check if the length of a list is less than x?
@AidenChow Not bad! [0]++l is the same as 0:l
A: Ken Iverson’s Favourite APL Expression?

AZTECCOHaskell, 26 25 bytes o l=zipWith(+)(0:l)l++[1] Try it online! Saved 1 thanks to @ovs New approach, it essentially do this: 0[1,2,1] + [1,2,1] = [1,3,3] + 1 Previous version 30 bytes o=(0#) x#(v:w)=x+v:v#w x#_=[x] Try it online!

2:57 AM
i mean, i didn't look it up if that's what you're suggesting
No, I'm just saying that's probably the optimal solution
HMQ: Given n, return the nth row of Pascal's triangle.
A: Sandbox for Proposed Challenges

tshSmallest Bit Rotate integresequencecode-golf Input a positive integer. Rotate it bits 0 or more bits. Output the smallest possible rotate result. For example, when input is 177 $$ 10110001_{(2)}=177 \\ 01100011_{(2)}=99 \\ 11000110_{(2)}=198 \\ 10001101_{(2)}=141 \\ 00011011_{(2)}=27 \\ 0011011...

Hint: you can match multiple patterns.
f 0 = [1]
f n = stuff
error: Not in scope: data constructor ‘F’ ???????
3:06 AM
use lowercase
uppercase is reserved for Type Stuff™
@UnrelatedString oh
@DLosc what the
not even gonna try to understand that
for example you would be able to use F if you'd done data MyAlgebraicType a = F a in which case you'd have F :: a -> MyAlgebraicType a
@AidenChow it's actually not that complex if you unpack all the infix stuff
3:10 AM
Incidentally, that do in your footer can be simplified to mapM (print.f) [3..7]
(which means now I actually know what mapM is)
@AidenChow It's based on my solution to the previous HMC. Applying iterate to that function, starting at [1], creates an infinite list representing the entirety of Pascal's triangle. Then the !! uses indexing to select a single row.
and mine is my solution but with a recursive infinite list
speaking of unpacking infix stuff it can actually be 44
dang ok thats actually smart, though idk what iterate does
3:13 AM
oh yeah recursive infinite lists are a really nice way to show off what haskell is
@AidenChow iterate f x = x:iterate f (f x)
@AidenChow iterate f x is a list [x, f x, f$f x, f$f$f x, ...]
@AidenChow iterate just repeats a function on a value to generate a lazy infinite list, so iterate(+1)1 will create a list of positive integers
i saw everyone else post their explanations, but posted mine anyway
ok uhh ill just assume yall are saying the same stuff, because i still dont really get it...
what does $ do??
function application
with different precedence and associativity
don't worry about it, it's irrelevant
f$f x is the same as f (f x)
3:16 AM
@UnrelatedString ah finally something i can understand
so iterate just applies the function over and over again?
@AidenChow An iterated function is when you apply the same function several times in a row, like f(f(f(x))). Haskell's iterate makes a list of the results if you apply the function 0 times, 1 time, 2 times, etc.
ok that seems to be a very helpful function, i will try to keep that in mind
you can go pretty far by searching for things on hoogle
@Nitrodon so what does mapM do?
3:19 AM
if you feel like something probably exists but you don't have the faintest clue what it's called, you can search for it by its type
In the context of the IO monad, for each element of the list [3..7], it applies the function (print.f) on it and does that action.
@UnrelatedString wdym by type
We're golfing everything and not including type annotations.
i'm not entirely sure how to explain type tbh
3:22 AM
The type a -> a represents a function from a to a.
how do i search for its type, is it like integer, boolean, function, etc.?
(fun aside: since haskell's polymorphism is parametric, id is the only possible distinct a -> a)
like wdym by searching for type
if for example you want a function that gets the length of list, you can search for [a] -> Int
The type of iterate would be (a -> a) -> a -> [a], since it takes a function and an a and returns a list of a.
3:23 AM
@Nitrodon so what is the difference between mapM and map?
@AidenChow Yes, but there's no function type: each function's type is based on the types of its arguments and its return value
and if you want a function that repeats a list some finite number of times, you can search Int -> [a] -> [a]
map will apply a function to each element of a list, and return a list.
@AidenChow spooky monads
as will fmap, which works on any functor
3:24 AM
fmap does effectively the same thing as map, but for any functor.
and has the nice infix synonym of <$>
3:59 AM
@JoKing Unfreeze please? ^^
as long as you do more than say thanks and let it freeze again :P
Lol, will do X^D
It's unfrozen.
oh yeah we should probably mention list comprehensions
JoKing or Bubbler, could you migrate the conversation starting from my "What's a monad?" question?
4:02 AM
and do more actual cmcs
...I think the relevant conversation is much longer than that?
probably the entire thing about functors
@JoKing whoa there is a haskell chat
4:07 AM
and there is LYAL
ayo im back
the frick happened here
why is there a bunch of msgs moved
because they were too technical for LYAL, I guess?
@Nitrodon oh, "too technical"? makes sense, i couldnt understand 90% of what yall were saying
4:18 AM
@UnrelatedString We were going to discuss list comprehension over here?
oh yeah
i don't know the exact specification of list comprehensions, but i think it's something like [element | a <- list, condition a], right? plus a lot of wiggle room for multiple lists and conditions
@JoKing what does <- do
it's part of the list comprehension syntax
does the same thing as it does in do notation pretty much
4:24 AM
so you could do a single element condition like [1|even a] to get [1] when a is even
It is a syntax indicating that a gets each element of list
oh yeah i totally forget you can just do that
[element | a <- list, condition a] is equivalent to python's [element for a in list if condition(a)]
@JoKing ok yep that makes sense
Haskell's is more powerful because you can pattern-match on a in a <- list like h:t <- list (which conveniently ignores elements of list that do not match the pattern)
4:32 AM
HMQ: Given n, return a list of the unique products of all pairs of ints that add to n, e.g. 6 => [1*5,2*4,3*3] => [5,8,9]
@JoKing Positive ints, I assume?
right, yes, forgot to specify
though, you know what, including non-positives can be a bonus challenge ha
@JoKing That'd be an infinite list, methinks
@JoKing In any order?
@DLosc totally fine to return wink, as long as you can prove it will eventually return everything
@Bubbler any order, i should probably also specify that the return should be [Int]
4:38 AM
wait no, I have to halve it anyway
violates both "unique" and "the return should be [Int]"
though that can be solved by just using div instead of /
@JoKing whats the difference
Yeah, this is at 29
div is integer division
4:43 AM
/ is real division, div is integer division (flooring)
i was trying to illustrate more complex list comprehension e.g. this, but i forgot about math shortcuts >.<
ah lol
I'm trying to write \a->(10-a)*a in point-free form. Thinking that =<< was a (reversed) S-combinator, I wrote (10-)=<<(*), but that didn't work. What am I doing wrong?
i still dont fully understand what point free form is
what indicates that some code is in point free form?
Oh--looks like I just had it backwards, lol
oh, it was =<<?
After our whole big discussion about >>= being a kind of flatMap generalization, I somehow got the idea it couldn't be applied to functions.
the Monad instance for functions is
(->) a is also a monad.
4:57 AM
Yeah. No need to go into why at the moment. :P
It's basically a box that you put a value into and get a value out of.
@AidenChow \a->(10-a)*a is not point free because it calls its argument by its name. (*)=<<(10-) is the same function but does not use its argument's name anywhere, which makes it point free.
all you have to know is (f=<<g) x = f (g x) x and (f<*>g) x = f x (g x)
and pure is const
@Bubbler hmm ok, how would you go about making point free code, and is it better than other forms
4:59 AM
"points" are the values the functions are acting on. a point free function is a function that doesn't mention those values explicitly, usually as a combination of other functions

« first day (4064 days earlier)      last day (795 days later) »