(=<<) 组合子的鸟名?

Bird name for the (=<<) combinator?

Haskell 鸟舍组合器将 (=<<) 列为:

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

有正式的鸟名吗?还是可以从已有的推导出来?

Is there an official bird-name for this?

我在 Data.Aviary.Birds 中找不到它,所以我想没有。如果有,它可能会在您链接的列表中被引用。

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

当然可以。最简单的可能是从签名相似的 starling 开始,然后用 flip 组合它,即

(=<<) = bluebird starling cardinal

也许会像这样:blackbird warbler bluebird 这就像

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

引用评论:

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 name is totally made-up.
mino :: (b -> a -> c) -> (a -> b) -> a -> c

虽然您不会在 the list 中找到它,但有些东西非常相似:

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

如果我们有办法以某种方式将 starling 扭曲成我们想要的...

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

这个神秘的 f 有一个相当笨重的类型,所以让我们把它缩写一下:x ~ b -> a -> cy ~ a -> b -> cz -> (a -> b) -> a -> c,我们有

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

再看一下列表显示这符合 queer 的结果类型:

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

进步!

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

至于g,有一个很好的候选人:

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

就是这样:

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

queer当然是cardinal bluebird(即反向函数组合),又回到了.


GHC其实可以帮你做这种推导:

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.

不过,如果你想要一个干净的输出,你必须轻轻地问:

{-# 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

starling 的类型注解会使定义 s 变得不必要;但是,这种风格会随着更复杂的表达式而变得非常丑陋。)

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.

上面描述的过程仍然涉及相当多的凝视列表,因为我们只使用无点威严的鸟类来计算它。但是,如果没有这些限制,我们可能会以不同的方式进行:

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

洞的类型为 a -> c,所以我们知道它是一个接受 a:

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

这里唯一需要 a 的是 g:

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

洞的类型现在是 b,唯一给出 b 的是 f:

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

这当然是通常定义的reader(=<<)。如果我们翻转 g,虽然...

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

... reader (<*>)(即 S 组合子)变得可识别:

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

然后我们可以将它写成 pointfree...

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

...并翻译成鸟语:

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