Pointfree在Haskell中返回一个元组

时间:2012-09-12 19:37:21

标签: haskell pointfree

一个无点函数可以返回一个元组吗?例如,以下内容可以用无点样式编写(其中f1,f2和f3已定义):

(\t -> (f1 t, f2 t, f3 t))

在这种情况下,我的f1,f2和f3是quot,mod,*和一些整数的组合。

(\f1,f2,f3 -> (\t -> (f1 t, f2 t, f3 t)))

是更一般的情况,相当于

(\f1,f2,f3,t -> (f1 t, f2 t, f3 t))

命名函数没问题,但我的示例是匿名的。 (命名示例如下)

f x = (f1 x, f2 x, f3 x)
f f1 f2 f3 x = (f1 x, f2 x, f3 x)
编辑:我只是好奇好玩,我不打算这样做。

5 个答案:

答案 0 :(得分:11)

你可以写

(\t -> (f1 t, f2 t, f3 t))

pointfree,它是

liftM (,,) f1 `ap` f2 `ap` f3

来自ap的{​​{1}}和来自Control.Monad的{​​{1}} Monad个实例。更可读的形式可能是(->) a变体

Control.Monad.Instances

然后你可以进一步指向免费

Control.Applicative

作为

(,,) <$> f1 <*> f2 <*> f3

但严重的是,你不应该这样做。保持可读性,这意味着一点点自由是好的,但不要过度。

答案 1 :(得分:4)

是。 &#34; lambdabot&#34; #haskell IRC频道上的IRC bot实际上有一个功能,可以为您提供给定功能的无点版本。在你的情况下,它说

\x -> (f x, g x, h x)

相当于

ap (liftM2 (,,) f g) h

答案 2 :(得分:4)

尽管applicative或monadic版本更简单,更短,但是一种可能暴露“含义”(以及你正在使用的Haskell类型的属性)的方法是使用Control.Arrow

uncurry (uncurry (,,)) . ((f &&& g) &&& h)

有点版本虽然优越。

这也暴露了你需要Hask的“笛卡尔”,但不是Hask的所有“封闭性”

 arrowized :: Arrow cat => cat a a1 -> cat a b1 -> cat a b -> cat a (a1, b1, b)
 arrowized f g h => arr (uncurry (uncurry (,,))) . ((f &&& g) &&& h)

答案 3 :(得分:2)

你可以像这样编写你的例子:

\f1 f2 f3 t -> (,,) (f1 t) (f2 t) (f3 t)

(,,)是一个带有3个参数的常用函数,因此在使其应用程序无点时没有什么特别之处。但是,它使用它的参数3次,所以它会很麻烦,而且可能不值得。

#haskell的Lambdabot说它是(ap .) . liftM2 (,,)。享受:)

答案 4 :(得分:2)

这里有一些关于对方答案的详细说明。

Control.Applicative的源代码中,我们找到了

instance Applicative ((->) a) where  -- (a ->) is meant here
    pure = const
    (<*>) f g x = f x (g x)

liftA3 f a b c = f <$> a <*> b <*> c

在GHCi中,我们得到了

Prelude Control.Applicative> :t liftA3 (,,)
liftA3 (,,) :: (Applicative f) => f a -> f b -> f c -> f (a, b, c)

因此,(t->)f liftA3 (,,) 正常运作:

liftA3 (,,) ~ (t->a) -> (t->b) -> (t->c) -> (t->(a,b,c))

即,在同一类型输入上给出三个函数时,调用 liftA3 (,,) f1 f2 f3 t 会产生三个(f1 t, f2 t, f3 t)

Prelude Control.Applicative> liftA3 (,,) (:[]) (quot 12) (`rem`3) 4
([4],3,1)


那么,它是如何运作的?通过liftA3的定义,然后是<*>的定义,

liftA3 (,,) f g h t = ((((,,) <$> f) <*> g) <*> h) t
    = (((,,) <$> f) <*> g) t (h t)
    = (((,,) <$> f) t (g t) (h t)

现在,(<$>) = fmapinstance Functor ((->) t)定义了fmap = (.),所以我们继续

    = (((,,) . f) t (g t) (h t)
    = (,,) (f t) (g t) (h t)
    = (f t, g t, h t)