使用Functors时提升策略

时间:2016-02-26 11:36:46

标签: haskell

假设我有一个功能

foo :: a -> b -> c -> d -> e
foo a b c d = somefn a b c d

以及一些回复我a, b, c and d的函数

getA :: a
getB :: b
getC :: f c
getD :: d

仅返回c的函数返回带有c

的仿函数

现在我打电话给网站

callfoo = foo getA getB getC getD

显然不会起作用,因为getC返回c的仿函数而不是c本身。所以唯一的方法似乎是

callfoo = (foo getA getB) <$> getC <*> getD

除了简单foo的调用在此处丢失之外,签名也会更改为callfoo :: f e。 保持简单的一种方法是(extract getC),但这是邪恶的,会让你进入Haskell-hell的特殊区域。我知道。

我的一般问题是: 我如何处理我主要使用非函数值的情况,但突然之一的值也迫使我提升所有其他值?

1 个答案:

答案 0 :(得分:1)

您可以使用do语法:

do
    c <- getC
    return (foo getA getB c getD)

如果您启用ApplicativeDo,则会使用有效的fmap表单,而不是可能效率低下的>>=return表单。

quasiquoter on Hackage for idiom brackets可以让你写

[i| foo (pure getA) (pure getB) getC (pure getD) |]

否则,几乎没有糖。有许多方法可以用现有的组合器来拼写你的操作,这些方法通常在所有情况下通用和紧凑之间进行权衡。一些例子包括:

flip (foo getA getB) getD <$> getC
(\c -> foo getA getB c getD) <$> getC
foo getA getB <$> getC <*> pure getD
foo <$> pure getA <*> pure getB <*> getC <*> pure getD