如何使用此类签名制作组合器?

时间:2018-02-28 05:50:42

标签: haskell combinators tacit-programming

我一直试图用这种类型的签名制作一个组合器:

(a -> b -> c) -> (c -> d -> e) -> a -> b -> d -> e

我已经通过Data.Aviary.Birds以及我能找到的所有隐性编程帮助网站,但无济于事。此外,如果有一个通用的算法来制作这些,我们将非常感激但不是必需的。

2 个答案:

答案 0 :(得分:7)

我们的定义将从这样开始:

L= {w | number of 010s in w is more than the number of 101s}

现在让我们填写缺失的部分。

我们需要foo :: (a -> b -> c) -> (c -> d -> e) -> a -> b -> d -> e foo abc cde a b d = e ;唯一的方法是将第二个函数应用于ec

d

我们已经获得e = cde c d ,但我们需要d。我们如何获得c?将第一个函数应用于ca

b

我们得到了这两个,所以我们已经完成了。

c = abc a b

我们可能就此止步。这是一个非常好的定义。

但如果我们想试着让它更简洁一点,那么我们首先要用foo :: (a -> b -> c) -> (c -> d -> e) -> a -> b -> d -> e foo abc cde a b d = e where e = cde c d c = abc a b

的定义来代替
e

然后是foo abc cde a b d = cde c d where c = abc a b

c

我们立即看到我们可以减少删除foo abc cde a b d = cde (abc a b) d

d

该类型现在略微更为通用。 foo abc cde a b = cde (abc a b) 已折叠为一个类型变量,因为它实际上可以是任何类型。

d -> e

我们现在可以在鸟舍看到我们的组合器实际上是黑鸟,翻转。

foo :: (a -> b -> c) -> (c -> de) -> a -> b -> de

事实上,如果我们看看黑鸟的来源,它看起来就像我们写的那样。

blackbird :: (c -> d) -> (a -> b -> c) -> a -> b -> d

foo :: (a -> b -> c) -> (c -> de) -> a -> b -> de
foo = flip blackbird

我们可以更专注吗?我们可能会考虑取消-- | B1 combinator - blackbird - specs 'oo'. blackbird :: (c -> d) -> (a -> b -> c) -> a -> b -> d blackbird f g x y = f (g x y)

abc

使用函数组合重写此嵌套

foo abc cde a b = cde (uncurry abc (a, b))

然后又回头了

foo abc cde a b = (cde . uncurry abc) (a, b)

现在我们可以切断两个参数。

foo abc cde a b = curry (cde . uncurry abc) a b

我们绝对应该停在这里。但是如果我们现在翻转参数

怎么办?
foo abc cde = curry (cde . uncurry abc)

重写右半边以使其无点

foo = flip $ \cde abc -> curry (cde . uncurry abc)

并且eta再次减少

foo = flip $ \cde abc -> (curry . ((cde .) . uncurry)) abc

并采取最后一个荒谬的步骤

foo = flip $ \cde -> curry . ((cde .) . uncurry)

我们现在无点!

答案 1 :(得分:6)

有一种非常简单的方法:作弊。让我们首先找出我们想要的功能。为此,我们转到Djinn。输入

f :: (a -> b -> c) -> (c -> d -> e) -> a -> b -> d -> e

然后又回来了

f a b c d = b (a c d)

尼斯。现在转到pointfree.io。粘贴在Djinn的定义中,它说

f = flip ((.) . (.))

完成。