News for hackers. Stuff that matters.
Re:Functors, Applicatives, and Monads in Pictures (2013) by tsimionescu on Thursday October 21, 2021 @05:22AM (#28942174)
I wonder why auto-curried function syntax has become so ubiquitous in explaining this. For anyone coming from a more traditional CS background, it's just extra cognitive overhead in understanding the meat of the argument.

For example,

  (a -> b,T a) -> T b
  (a -> b,T<a>) -> T<b>
Is just as good in explaining what bind means as the curried version, but more familiar to the vast majority of programmers and CS graduates.

Note: I do understand why auto-currying is extremely useful for doing functional programming, and I have no objections to teaching it. I just don't think it's important for teaching functors, applicatives and monads.

In a separate nit-pick, these three function definitions don't mean much on their own, and there are many pure functions that satisfy them without forming a functor/applicative/monad.

Re:Functors, Applicatives, and Monads in Pictures (2013) by dragonwriter on Thursday October 21, 2021 @05:36AM (#28942247)
> I wonder why auto-curried function syntax has become so ubiquitous in explaining this.

Probably because Haskell (and related languages) use it.

> For anyone coming from a more traditional CS background, it's just extra cognitive overhead in understanding the meat of the argument

I find that curried function signatures are slightly lower cognitive overhead after a bit of exposure, and while I can see that its the kind of thing that is likely to vary from person to person a bit, I can't see that it's likely to be a big thing either way.

Re:Functors, Applicatives, and Monads in Pictures (2013) by Twisol on Thursday October 21, 2021 @05:28AM (#28942207)
> I wonder why auto-curried function syntax has become so ubiquitous in explaining this.

I think it's primarily because this is the form you use them in in a language like Haskell. Most explanations are exported from Haskell in one way or another, so they're deeply colored by Haskellisms.

It's the same reason why `ap` and `bind` are generally preferred over `times` and `join` -- in Haskell you can even use `f <$> a <*> b`, which is a deeply clever use of infix `fmap` and `ap` that drives a syntactic analogy with regular function application, `f a b`. Try doing that in another language and you'll barf. And do-notation desugars most cleanly into >>=, so that's where Haskell-oriented explanations start from.

If you implement these in Java (which you can, you just can't abstract over T), it looks like this:

    class List<A> {
      <B> List<A> map(Function<A, B> f) { ... }
      
      <B, C> List<C> map2(List<B> other, BiFunction<A, B, C> f) { ... }

      <B> List<B> flatMap(Function<A, List<B>> f) { ... }

      // bonus; note that these make more sense static
      static <A, B> List<Pair<A, B>> times(List<A> as, List<B> bs) { ... }

      // in fact, this one has to be static
      static <A> List<A> join(List<List<A>> aas) { ... }
    }
That is, the second argument `T a` in the top poster's comment becomes the implicit `this` parameter for instance methods. I find the `static` alternatives often make more syntactic sense in context; just goes to show that one language's norms don't always transfer.
Re:Functors, Applicatives, and Monads in Pictures (2013) by tel on Thursday October 21, 2021 @06:08PM (#28951426)
You can also look at the Scala implementations if you like. Scala has HKTs so you can write it all directly.

   trait Functor[F[_]] {
     def map[A, B](f: A => B)(x: F[A]): F[B]
   }

   trait Applicative[F[_]] extends Functor[F] {
     def pure[A](a: A): F[A]
     def apply[A, B](f: F[A => B])(x: F[A]): F[B]
     def product[A, B](xa: F[A], xb: F[B]): F[(A, B)]
   }

   trait Monad[F[_]] extends Applicative[F] {
     def bind[A, B](f: A => F[B])(x: F[A]): F[B]
     def join[A](x: F[F[A]]): F[A]
   }
Re:Functors, Applicatives, and Monads in Pictures (2013) by dunefox on Thursday October 21, 2021 @05:51AM (#28942317)
That version is extremely noisy, imo.
Re:Functors, Applicatives, and Monads in Pictures (2013) by marcosdumay on Thursday October 21, 2021 @11:17AM (#28945668)
I once had to add logging to a large set of methods in C#, so I thought, well, let's make a function decorator like Python or Haskell, there's no reason it wouldn't work on C#.

Well, it indeed worked perfectly well. But the amount of noise added to satisfy the type checker was larger than reimplementing the log procedure at each place.

Re:Functors, Applicatives, and Monads in Pictures (2013) by Twisol on Thursday October 21, 2021 @06:46AM (#28942664)
The version in Java? Yes, because it's Java.
Re:Functors, Applicatives, and Monads in Pictures (2013) by lkitching on Thursday October 21, 2021 @06:54AM (#28942724)
I think it's clearer to think of map as a function

    (a -> b) -> (f a -> f b)
i.e. one which lifts function application over values of the functor. This is then analagous to the role of `f` for mapping types, and corresponds to the concept of a functor in the category of types. This relationship is harder to see in the tupled version. There's a similar argument for e.g.

    =< :: (a -> m b) -> (m a -> m b)
Re:Functors, Applicatives, and Monads in Pictures (2013) by lkuty on Saturday October 23, 2021 @03:55AM (#28966545)
Typo: =<<
Re:Functors, Applicatives, and Monads in Pictures (2013) by dunefox on Thursday October 21, 2021 @09:40AM (#28944193)
> it's just extra cognitive overhead in understanding the meat of the argument.

Compared to other versions I have seen this Haskell-style is the most elegant and understandable.