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?

asked Mar 21, 2018 at 17:16

3 Answers 3

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
34.5k7 gold badges88 silver badges159 bronze badges
answered Mar 21, 2018 at 17:34
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks! I had just applied cardinal and starling without composing them - that fixed it :)
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: repl.it/@DavidKomer/SetFromLens
@davidkomer and interesting stuff with X combinator twitter.com/xgrommx/status/756801731846103040
(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.
4

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

(...) = (.) . (.) -- blackbird
(.) -- bluebird
join -- warbler
-- and your function will be 
f = join ... (.)
answered Mar 21, 2018 at 18:23

2 Comments

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!)
This is like LEGO :)
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
answered Mar 26, 2018 at 7:18

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.