Hey guys, what do you think of this? Useful? https://gist.github.com/MarkusPfundstein/49ed6c91e66fce4e6873b651bc7aaf11

its possible to do some real crazy patterns (see m5 and m6)

That's really cool!

I actually really like that interface for handling the insanity that is JS's arrays so a big :plus1: from me

thanks :-) the most annoying part is

that in order to match the ‘type’ of a string. you must do typeof

which retursn a string -.-

I'm curious though, would it be possible to replace the strings with constructors?

So instead of

`'string'`

, you'd have `String`

I tried

Then it could work for user-defined constructibles as well.

the repl makes it null -.-

For user defined types it works

See m6

```
class ABox {
constructor(v) {
this.v = v;
}
}
const m6 = matchC([new ABox(5), [new ABox(10), new ABox(20)]])
.when([ABox, 5], ([a, b]) => [false, a, b])
.when([ABox, [ABox, ABox]], ([a, b]) => [true, a, b])
.otherwise(_ => 'no match’);
```

Ooh, that's good.

even works with inheritance

But it seems weird that some types would be strings while others would be valid constructibles...

i know

The matching on values is nice though.

and functions :-)

`.when(['_', [100, 100], p => p === 100], ([a, b, c]) => [true, a, b, c])`

I think that has a lot of power

yes. I hope so. Need to iron out potential bugs I guess but it could be useful

Would that be something for ramda maybe?

@MarkusPfundstein why not just use

`cond`

?
@MarkusPfundstein also https://github.com/natefaubion/matches.js

didn’t know it existed :-)

yeah matches is ugly

i dont like ti

@MarkusPfundstein reason?

the style how you define your patterns

large strings

@xgrommx as a sidenote, matches.js is deprecated. maybe you referred to sparkler?

@alexandrethsilva also outdated https://github.com/natefaubion/sparkler

ah yeah, true :D

just saw that this natefaubion guy has some really nice stuff

but anyways, off topic

but anyways, off topic

Does Ramda have anything similar to http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Function.html#v:on ?

@afhole You can use

`useWith`

to mimic it.`const on = (final, transform) => useWith(final, [transform, transform])`

lol

@MarkusPfundstein :+1:

now i just have to get it in shape so that it can be used by the browser as well I guess

I only do node

no idea how browser stuff works

no idea how browser stuff works

You can just browserify it. I think your module is awesome, for what it's worth. Keep on keepin' on!

thanks :-)

I check browserify

It wouldn't be possible to get it to work like Haskell's pattern matching, would it?

Something about:

```
map :: (a->b) -> [a] -> [b]
map f [] = []
map f (x:xs) = f x : map f xs
```

is just such a neat syntax for pattern matching

Granted, you shouldn't actually

`map`

in any language without TCO using recursion but still
actually

I did s.th. like this

mom

need to start laptop

Mostly, just letting the user write their strings with the infix operator

I translated the patterns here: http://homepages.inf.ed.ac.uk/wadler/papers/marktoberdorf/baastad.pdf

this is what you can do then for instance:

```
const [Term, Con, Div] = defData({
Term: {
Con: ['a'],
Div: ['t', 'u']
}
});
/*
* first example - Maybe Monad
*/
const eval1 = (term) =>
match(term)
.when(Con, t => Maybe.of(t.a))
.when(Div, d => eval1(d.t).flatMap(a => eval1(d.u).flatMap(b => Maybe.of(a/b))))
.get();
```

@MarkusPfundstein probably this isn't necessary https://github.com/MarkusPfundstein/pmatch-js/blob/master/match.js#L20

(old version of match which didn’t allow deep nesting)

@xgrommx You got me :P

@afhole isn't that basically what () is, in a way? It's just not available as an infix operator

@LeonineKing1199 this isn't complicate https://jsbin.com/bumuqa/2/edit?html,js,output (refarding map)

i.e. you can't do

`fn value`

nor can you do `fn () value`

you have to do `fn(value)`

I actually have no idea how the spread operator works lol XD

I'm still using peasant JS

```
> [a,b,...c] = [1,2,3,4,5]
[ 1, 2, 3, 4, 5 ]
> a
1
> b
2
> c
[ 3, 4, 5 ]
```

Hey, that's pretty nice

That's a Node 6 feature, right?

yopp

@MarkusPfundstein

`let {a:b =10, c} = {d:1, f:20, c:10}`

or with ramda, doing

`ap([x=>x+1])([5])`

in containers is ultimately something similar
Yeah, still on Node 4

:O

@MarkusPfundstein rename and default value)

i migrated our whole prod. environment the day node6 became LTS :P

yeah, destructuring is awesome. Its really a game changer. Destructuring and arrows also make promise based programming much more cool.

the day node6 became LTS

4 is still LTS ;)

myP.then(([val,1,val2]) => {x: val1*val2}).then(({x}) => x)

Also this is my favorite now (if you use desktop) https://github.com/princejwesley/Mancy/

Won't this overflow your stack though:

```
const map = (f, xs) => {
let [head, ...tail] = xs;
switch(xs.length) {
case 0:
return [];
default:
return [f(head), ...map(f, tail)];
}
}
```

Does Node have TCO?

no

afaik nope

not yet

I'm always skeptical of people using JS for big data so I guess a recursive map actually is alright XD

MANCY :O :O :O

THIS … IS …. WHAT … I …. NEED

fuck ./node :P

If anything, it only further punishes people for using JS for big data

I think we don't need implement FP in js! Just use haskell or purescript :smile:

@xgrommx That's cool!

@MarkusPfundstein really powerful tool

@xgrommx tell that my tech lead -.-

the recursive map isn't tco-iazble though, right? because the function isn't the last thing returned

Yeah, I know it's possible in circumstances where you do that.

But maybe not in that case..

Eh

@dtipson so, you can use Y combinator with memoizing

You guys, just use a loop XD

loops are much more difficult

TCO does that for you anyway

recursion is like the easiest thing for most algorithmn

```
const Y = (f, c = new Map, r = void 0) => a => c.has(a) ? c.get(a) : (r = (f( (n ) => (Y(f,c))( n )))( a ), c.set(a, r), r);
const reduce = f => Y(g => y => xs => xs.length < 1 ? y : g(f(y)(head(xs)))(tail(xs)));
```

map we can implement with reduce =)

Recursion is iteration, man.

implement breadt-first search with a loop

and wiht recursion

recursion is much more straightforward

```
const fib = Y(f => n => n <= 1 ? n : f(n - 1) + f(n - 2));
const fact = Y(f => n => n < 2 ? 1 : f(n-1) * n)
```

Yeah... I remember the first time I learned about recursion depth from that too...

as I understand it, the point of Y is to implement recursion in combinator systems that don't allow assignment. But in js, we can just assign a function a name and then reference it directly

So Y becomes complete overkill

I think there's formulaic ways you can convert recursion to iteration though.

Y looks awesome but I don’t understand it :P

@dtipson no, Y combinator incapsulate recursion

unless you are saying that makes a recursion that's hard to express in a TCOish way into something that is TCO-izeable

I like this implementation of

`reduce`

as well:```
const fold = (f, seed, xs) => {
let [head, ...tail] = xs;
switch(xs.length) {
case 0:
return seed;
default:
return fold(f, f(seed, head), tail);
}
}
```

but in the function above, f(n-1) * n is not TCO, because the function is not the last thing run

that reduce version looks TCO to me, otoh

good catch @dtipson

Eh. The problem with that is that I think it only evaluates the function as the recursion stack unwinds.

`const curry = (f, ...args) => (f.length <= args.length) ? f(...args) : (...more) => curry(f, ...args, ...more);`

I bet a loop would be significantly more performant

to make map above TCO I think you would have to prepend and then reverse at the end

(more of an autocurry)

@LeonineKing1199 yes. in JS most definitely

```
const head = ([x, ...t]) => x;
const tail = ([x, ...t]) => t;
/*
* composes a chain of function into a single function
*/
const compose = (f, ...rest) => (x) =>
rest.length === 1
? head(rest)(f(x))
: compose(head(rest), ...tail(rest))(f(x));
```

I might get flack for this but it's kind of awesome, the Haskell runtime is implemented in C, I think XD

in my experience trying to play with it, the problem with implementing operations over lists using rest parameters is that you either have to reverse the list at some point, or give up TCO

yopp

at University Bachelor, we had to use Prolog for all Logic related programming… You always needed to get TCO right, which mostly involved reverse at the end :P

Omg, I forgot C-- was a thing

wtf is C— ?

```
function fibonacci(n) {
var num;
if (n >= 2) {
num = fibonacci(n - 1) + fibonacci(n - 2);
} else {
num = n
}
return num;
}
function fibonacci2(n) {
function go(n, a, b) {
switch(n) {
case 0:
return a;
default:
return go(n - 1, b, a + b);
}
}
return go(n, 0, 1);
}
function fibonacci3(n) {
var sq5 = Math.sqrt(5);
var a = (1 + sq5) / 2;
var b = (1 - sq5) / 2;
return Math.ceil((Math.pow(a, n) - Math.pow(b, n)) / sq5);
}
```

last version :smile:

haha fibonacci3

I remember that from an assignment :D :D :D

first year, first semester, first course (!!!)

wtf is C— ?

About two steps below C++ :P

fibonacci2 is a trampoline, right?

no, regular recursion

trampoline is if you jump between 2 functions

C-- is low level in Haskell after Core

Speaking of trampolines, there's this awesome talk about Scala vs the paradigm of FP

link?

I don't wanna post it because the title is flame bait

send me PM

:D

But it's this guy basically talking about all the abstraction leaks in Scala as it deals with the JVM

aja, lack of TCO :P

clojure has recur for that

And trampolines are one of them because I guess people were creating such large monadic compositions that they overflew their stacks

no idea how its implemented,

I sent you the link

So yeah, be careful about the languages you choose. FP is kind of built on TCO

My point! use haskell and purescript :smile:

but we need adt in js :smile:

Saying JS needs types is a massive understatement lol XD

wtf?!

I can't even consider a language worth using if its verbosity doesn't at least match:

```
template <
typename T,
typename = std::enable_if<std::is_floating_point<T>::value>::type
>
```

The more words the better XD

```
class Tree {
constructor(left, right) {
this.left = left;
this.right = right;
}
}
class Node {
constructor(value) {
this.value = value;
}
}
const T = (l, r) => new Tree(l, r);
const N = v => new Node(v);
const dfs = (t) => match(t)
.when(Node, v => console.log(v.value))
.when(Tree, t => { dfs(t.left); dfs(t.right)})
.otherwise(_ => 'error');
dfs(T(T(N(5), T(N(7), N(1))), T(N(-1), N(8))));
// 5
7
1
-1
8
```

without recursion this would be a pain though. I hope we can get TCO into node7++

@MarkusPfundstein https://gist.github.com/xgrommx/eaadc9f5be7fcaa6e4f59010277576c5

Forget TCO, I just want this to throw:

`[] + {}`

:thumbsup:

‘5’ + 3

:P

One fire at a time, man.

TCO would be nice but it's not more important than silently doing whatever with such gross type mismatches

@xgrommx yeah, I need to check union-types. wasn’t aware of them since… yesterday?

I wonder how much websites would break if they would throw [] + {}

you have no idea what kind of js you encouter in the wild

Who's coding like that in first place and then actually relying on it? O_o

@MarkusPfundstein also https://github.com/puffnfresh/daggy but union-type is my choose

@MarkusPfundstein https://github.com/FGRibreau/match-when

It looks like the new Folktale will have an ADT module as well.

@xgrommx thx

@Bradcomp ?

similar to daggy's?

```
const fibbonacci = (n) => {
const go = (n, a, b) => {
return match(n)
.when(0, _ => a)
.otherwise(_ => go(n - 1, b, a +b));
}
return go(n, 0, 1);
}
console.log(fibbonacci(25));
const factorial = (n) => match(n)
.when(0, _ => 1)
.otherwise(n => n * factorial(n - 1));
console.log(factorial(10))
```

kinda works :-)

maybe I make the second parameter to when not necessarily a function

probably contains multiple errors and misstatements in the docs, but I had fun exploring how to create types with a similar pattern to daggy's here: https://github.com/dtipson/NELs

implements linked lists, circular linked lists, circular doubly linked lists (which has been done a million times before, but was a fun learning exercise). Most interesting/useful for the comonad and generator interfaces

@xgrommx

```
const mappy = (f, xs) => match(xs)
.when([], v => [])
.otherwise(([x, ...xs]) => [f(x), ...mappy(f, xs)]);
```

@dtipson nice. what is the actual literature abotu this?

about linked lists? Just your basic cons lists, but circular. So in the extreme case, a list of one thing has a .before/.tail that link to itself, and so on, forming a ring. The FL interfaces like map walk the list finitely, generators can iterate infinitely. It's a much more useful/intelligible structure for cellular automata using .extend, for instance. https://goo.gl/DdKYZL

@dtipson maybe it should be like

`S = b => f => x => (b(x))(f(x))`

https://github.com/dtipson/NELs/blob/36abef3d0651bd12d050eb7545bb267c622d4d74/src/utility/pointfree.js#L11 ?
(that uses an extend method that just pretends native Arrays are circular, an actual circular list is even more straightforward)

no about union types etc

that's if b is not curried

I have it in two flavors in another repo

`const S = f => g => x => f(x)(g(x)); const S2 = f => g => x => f(x, g(x));`

I actually have only found one usage for that combinator recently: in implementing Function.prototype.ap

it's pretty neat tho

```
let x = \f -> f(\x y -> x)(\x y z -> x z $ y z)(\x y -> x)
let s = x (x x)
let k = x x x
let b = s (k s) k
let lift = b(b(s))(b)
let i = s k k
let w = s s (s k)
let w'' = b (b w)
let c = s (b b s) (k k)
let q = c b
let join = w;
let bind' = w'' b
let bind = w'' q
let fish = b (b (b w)) (c (b b b))
let fish' = c fish
-- comonad
let extract = k i
let duplicate = w b
let extend = b (b duplicate) b
```

ooo, definitely have to work through that definition of extend

looks very instructive

@dtipson this is functor, monad, applicative for Function with only pointfree style (combinators calculus)

and comonad :smile:

yeah, it's super neat

it was just for fun :smile:

also only pointfree

```
import Prelude (Show, print, (++), (*), ($))
infixl 4 <*>, <**>, <*, *>, <$>, <$$>, <$
infixl 1 >>=, >>
infixr 1 =<<
s x y z = (x z)(y z)
k x y = x
i = s k k
b = s (k s) k
c = s (b b s) (k k)
w = s s (s k)
w'' = b (b w)
q = c b
liftA2 = b (b (<*>)) (<$>)
data Maybe a = Just a | Nothing deriving (Show)
foldr f z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
concatMap = b (c foldr ([])) (b (c (++)))
maybe n f a = case a of
Just v -> f v
Nothing -> n
class Functor f where
fmap, (<$>) :: (a -> b) -> f a -> f b
(<$>) = fmap
(<$$>) :: f a -> (a -> b) -> f b
(<$$>) = c $ (<$>)
(<$) :: a -> f b -> f a
(<$) = b (<$>) k
class (Functor f) => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
(*>) :: f a -> f b -> f b
(*>) = b (<*>) (i <$)
(<*) :: f a -> f b -> f a
(<*) = liftA2 k
(<**>) :: f a -> f (a -> b) -> f b
(<**>) = liftA2 (c ($))
class (Applicative f) => Monad f where
(>>=) :: f a -> (a -> f b) -> f b
(=<<) :: (a -> f b) -> f a -> f b
(=<<) = c $ (>>=)
(>>) :: f a -> f b -> f b
(>>) = b (c b k) (>>=)
join :: f (f a) -> f a
join = (>>= i)
instance Functor Maybe where
fmap = b (maybe Nothing) (b Just)
instance Functor ((->) r) where
fmap = b
instance Functor [] where
fmap = b concatMap (b (:[]))
instance Applicative Maybe where
pure = Just
(<*>) = c $ b (maybe Nothing) (<$$>)
instance Applicative [] where
pure = (:[])
(<*>) = b (c b (c fmap)) (c concatMap)
instance Applicative ((->) r) where
pure = k
(<*>) = s
instance Monad Maybe where
(>>=) = c $ maybe Nothing
instance Monad ((->) r) where
(>>=) = w'' q
instance Monad [] where
(>>=) = c concatMap
```

in js generators could be use as Traverse

`[Tree a] -> Tree [a]`

https://jsbin.com/dehetas/3/edit?html,js,console