Reputation: 3078
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
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
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
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