davidkomer
davidkomer

Reputation: 3078

Bird name for the (=<<) combinator?

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?

Upvotes: 4

Views: 1010

Answers (3)

duplode
duplode

Reputation: 34378

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

Upvotes: 1

Bergi
Bergi

Reputation: 664620

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

Upvotes: 5

xgrommx
xgrommx

Reputation: 1

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

(...) = (.) . (.) -- blackbird
(.) -- bluebird
join -- warbler
-- and your function will be 
f = join ... (.)

Upvotes: 4

Related Questions