4

The Haskell aviary combinators lists (=<<) as:

(a -> r -> b) -> (r -> a) -> r -> b

Is there an official bird-name for this? Or can it be derived via the pre-existing ones?

davidkomer
  • 3,020
  • 2
  • 23
  • 58

3 Answers3

5

Is there an official bird-name for this?

I can't find it in Data.Aviary.Birds, so I suppose there's not. If there was, it probably would've been referenced in the list you linked.

Or can it be derived via the pre-existing ones?

Surely. The easiest might be to start with the starling whose signature is similar, and just compose it with flip, i.e.

(=<<) = bluebird starling cardinal
duplode
  • 33,731
  • 7
  • 79
  • 150
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Thanks! I had just _applied_ cardinal and starling without composing them - that fixed it :) – davidkomer Mar 21 '18 at 18:05
  • Btw not sure if I am just mixing something up in the order between Haskell <-> Javascript but I ended up with Bluebird Starling Cardinal ... proof of concept: https://repl.it/@DavidKomer/SetFromLens – davidkomer Mar 21 '18 at 20:01
  • 1
    @davidkomer also two old my tweets :) https://twitter.com/xgrommx/status/788346309287809025 https://twitter.com/xgrommx/status/823648079828185088 – xgrommx Mar 21 '18 at 21:44
  • 1
    @davidkomer and interesting stuff with X combinator https://twitter.com/xgrommx/status/756801731846103040 – xgrommx Mar 21 '18 at 21:50
  • 1
    (1) @davidkomer `bluebird starling cardinal` it is indeed (or, in another dialect, `(<*>) . flip`). (2) This definition (and also, possibly, the fact that `(=<<)` isn't regarded as a distinct species of bird) reflects how `(<*>)` and `(=<<)` for functions (the reader functor) [are essentially the same thing](https://stackoverflow.com/a/40136614/2751851). – duplode Mar 22 '18 at 01:17
4

maybe will be correctly like: blackbird warbler bluebird this is like

(...) = (.) . (.) -- blackbird
(.) -- bluebird
join -- warbler
-- and your function will be 
f = join ... (.)
xgrommx
  • 461
  • 3
  • 15
  • Btw do you have any advice on how to combine combinators to get a specific signature? I feel like I'm missing some trick (my current technique of staring at a list and doing mental gymnastics doesn't scale too well!) – davidkomer Mar 22 '18 at 14:36
  • 1
    This is like LEGO :) – xgrommx Mar 22 '18 at 17:43
1

Quoting a comment:

Btw do you have any advice on how to combine combinators to get a specific signature? I feel like I'm missing some trick (my current technique of staring at a list and doing mental gymnastics doesn't scale too well!)

Let the types guide you. You are looking for:

-- This name is totally made-up.
mino :: (b -> a -> c) -> (a -> b) -> a -> c

While you won't find it in the list, there is something quite similar:

starling :: (a -> b -> c) -> (a -> b) -> a -> c

If only we had a way to somehow twist starling into what we want...

mino :: (b -> a -> c) -> (a -> b) -> a -> c
mino = f starling
-- f :: ((a -> b -> c) -> (a -> b) -> a -> c) -> (b -> a -> c) -> (a -> b) -> a -> c

This mysterious f has a rather unwieldy type, so let's abbreviate it for a moment: with x ~ b -> a -> c, y ~ a -> b -> c and z -> (a -> b) -> a -> c, we have

f :: (y -> z) -> x -> z

Another look at the list shows this fits the result type of queer:

queer :: (a -> b) -> (b -> c) -> a -> c

Progress!

mino :: (b -> a -> c) -> (a -> b) -> a -> c
mino = queer g starling
-- g :: x -> y
-- g :: (b -> a -> c) -> a -> b -> c

As for g, there is a great candidate near the top of the list:

cardinal :: (a -> b -> c) -> b -> a -> c

And there it is:

mino :: (b -> a -> c) -> (a -> b) -> a -> c
mino = queer cardinal starling

queer, of course, is cardinal bluebird (i.e. reverse function composition), which leads us back to Bergi's bluebird starling cardinal.


GHC can actually assist you with this kind of derivation:

import Data.Aviary.Birds

mino :: (b -> a -> c) -> (a -> b) -> a -> c
mino = _f starling
GHCi> :l Mino.hs
[1 of 1] Compiling Main             ( Mino.hs, interpreted )

Mino.hs:4:8: error:
    * Found hole:
        _f
          :: ((a0 -> b0 -> c0) -> (a0 -> b0) -> a0 -> c0)
             -> (b -> a -> c) -> (a -> b) -> a -> c
      Where: `b0' is an ambiguous type variable
             `a0' is an ambiguous type variable
             `c0' is an ambiguous type variable
             `b' is a rigid type variable bound by
               the type signature for:
                 mino :: forall b a c. (b -> a -> c) -> (a -> b) -> a -> c
               at Mino.hs:3:1-43
             `a' is a rigid type variable bound by
               the type signature for:
                 mino :: forall b a c. (b -> a -> c) -> (a -> b) -> a -> c
               at Mino.hs:3:1-43
             `c' is a rigid type variable bound by
               the type signature for:
                 mino :: forall b a c. (b -> a -> c) -> (a -> b) -> a -> c
               at Mino.hs:3:1-43
      Or perhaps `_f' is mis-spelled, or not in scope
    * In the expression: _f
      In the expression: _f starling
      In an equation for `mino': mino = _f starling
    * Relevant bindings include
        mino :: (b -> a -> c) -> (a -> b) -> a -> c (bound at Mino.hs:4:1)
  |
4 | mino = _f starling
  |        ^^
Failed, no modules loaded.

If you want a clean output, though, you have to ask gently:

{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE PartialTypeSignatures #-}

import Data.Aviary.Birds

mino :: forall b a c. (b -> a -> c) -> (a -> b) -> a -> c
mino =
    let s :: (a -> b -> c) -> _
        s = starling
    in _f s

(A type annotation to starling would make defining s unnecessary; that style, however, would get ugly very quickly with more complicated expressions.)

GHCi> :l Mino.hs
[1 of 1] Compiling Main             ( Mino.hs, interpreted )

Mino.hs:10:8: error:
    * Found hole:
        _f
          :: ((a -> b -> c) -> (a -> b) -> a -> c)
             -> (b -> a -> c) -> (a -> b) -> a -> c
      Where: `b' is a rigid type variable bound by
               the type signature for:
                 mino :: forall b a c. (b -> a -> c) -> (a -> b) -> a -> c
               at Mino.hs:6:1-57
             `a' is a rigid type variable bound by
               the type signature for:
                 mino :: forall b a c. (b -> a -> c) -> (a -> b) -> a -> c
               at Mino.hs:6:1-57
             `c' is a rigid type variable bound by
               the type signature for:
                 mino :: forall b a c. (b -> a -> c) -> (a -> b) -> a -> c
               at Mino.hs:6:1-57
      Or perhaps `_f' is mis-spelled, or not in scope
    * In the expression: _f
      In the expression: _f s
      In the expression:
        let
          s :: (a -> b -> c) -> _
          s = starling
        in _f s
    * Relevant bindings include
        s :: (a -> b -> c) -> (a -> b) -> a -> c (bound at Mino.hs:9:9)
        mino :: (b -> a -> c) -> (a -> b) -> a -> c (bound at Mino.hs:7:1)
   |
10 |     in _f s
   |        ^^
Failed, no modules loaded.

The process described above still involves quite a bit of staring at the list, as we are working it out using nothing but the birds in their pointfree majesty. Without such constraints, though, we would likely proceed in a different manner:

mino :: (b -> a -> c) -> (a -> b) -> a -> c
mino g f = _

The hole has type a -> c, so we know it is a function that takes an a:

mino :: (b -> a -> c) -> (a -> b) -> a -> c
mino g f = \x -> _
-- x :: a

The only other thing that takes an a here is g:

mino :: (b -> a -> c) -> (a -> b) -> a -> c
mino g f = \x -> g _ x

The type of the hole is now b, and the only thing that gives out a b is f:

mino :: (b -> a -> c) -> (a -> b) -> a -> c
mino g f = \x -> g (f x) x

This, of course, is the usual definition of the reader (=<<). If we flip g, though...

mino :: (b -> a -> c) -> (a -> b) -> a -> c
mino g f = \x -> flip g x (f x)

... the reader (<*>) (i.e. the S combinator) becomes recogniseable:

mino :: (b -> a -> c) -> (a -> b) -> a -> c
mino g f = \x -> (<*>) (flip g) f x

We can then write it pointfree...

mino :: (b -> a -> c) -> (a -> b) -> a -> c
mino = (<*>) . flip

... and translate to birdspeak:

mino :: (b -> a -> c) -> (a -> b) -> a -> c
mino = bluebird starling cardinal
duplode
  • 33,731
  • 7
  • 79
  • 150