Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
无点返回Haskell中的元组_Haskell_Pointfree - Fatal编程技术网

无点返回Haskell中的元组

无点返回Haskell中的元组,haskell,pointfree,Haskell,Pointfree,无点函数能否返回元组?例如,可以用无点样式编写以下内容(其中定义了f1、f2和f3): 在本例中,我的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)) ap (liftM2 (,,) f g) h 命名函数是可以的,但我的示例是匿名的。(命名示例如下) 编辑:我只是好奇好玩,我不打算这么做

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

在本例中,我的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))
ap (liftM2 (,,) f g) h
命名函数是可以的,但我的示例是匿名的。(命名示例如下)

编辑:我只是好奇好玩,我不打算这么做。

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

\x -> (f x, g x, h x)
相当于

(\f1,f2,f3,t -> (f1 t, f2 t, f3 t))
ap (liftM2 (,,) f g) h
你可以写

(\t -> (f1 t, f2 t, f3 t))
无意义的,它是

liftM (,,) f1 `ap` f2 `ap` f3
使用
Control.Monad
中的
ap
Control.Monad.Instances中的
Monad
实例
(>)a
。一种更具可读性的形式可能是
控件.Applicative
变体

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

\f1 f2 f3->(,)f1 f2 f3
=\f1 f2->((,)f1 f2)
=\f1 f2->()((,)f1 f2)
=\f1 f2->(()。(,)f1))f2
=\f1->()。(,)f1)
=\f1->()。()(,)f1)
=\f1->((()).()(,)f1
= (() .) . () . () (,,)

但说真的,你不应该。保持可读性,这意味着有点无点是好的,但不要做得太多。

您可以这样编写示例:

\f1 f2 f3 t -> (,,) (f1 t) (f2 t) (f3 t)
(,)是一个具有3个参数的常用函数,因此使其应用程序无需任何特殊设置。然而,它使用了它的论点3次,所以它会很麻烦,而且可能不值得


哈斯克尔的拉姆达博特说这是
(美联社)。liftM2(,)
。享受:)

尽管应用程序或一元版本更简单、更短,但一种可能揭示“含义”(以及您正在使用的Haskell类型类别的属性)的方法是使用Control.Arrow

uncurry (uncurry (,,)) . ((f &&& g) &&& h)
不过,pointfull版本更优越

这也暴露出你需要Hask的“卡特尔主义”,但不是Hask的所有“封闭性”


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

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
因此,使用
(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
,然后定义


我喜欢lambdabot使用monad函数的方式。我认为这个答案比我的好得多,我主要是转发lambdabot给出的。特别是,我喜欢
控件.Applicative
变体!顺便说一下,不要同时使用
quot
mod
。使用
quot
rem
(或仅使用
quotRem
)或使用
div
mod
(或仅使用
divMod
)。这些配对都有保证,即
quotRem m n=(q,r)
意味着
n*q+r=m
(对于
divMod
)也是如此。顺便问一下,为什么有两对呢?
quotRem
divMod
在负数上有不同的行为
divMod
总是返回一个正的
mod
部分,但是
quotRem
通常要快一点。
 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)
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
Prelude Control.Applicative> :t liftA3 (,,)
liftA3 (,,) :: (Applicative f) => f a -> f b -> f c -> f (a, b, c)
liftA3 (,,) ~ (t->a) -> (t->b) -> (t->c) -> (t->(a,b,c))
liftA3 (,,) f g h t = ((((,,) <$> f) <*> g) <*> h) t
    = (((,,) <$> f) <*> g) t (h t)
    = (((,,) <$> f) t (g t) (h t)
    = (((,,) . f) t (g t) (h t)
    = (,,) (f t) (g t) (h t)
    = (f t, g t, h t)