我在$||包中找到了parallel:
-- Strategic function application
{-
These are very handy when writing pipeline parallelism asa sequence of
@$@, @$|@ and @$||@'s. There is no need of naming intermediate values
in this case. The separation of algorithm from strategy is achieved by
allowing strategies only as second arguments to @$|@ and @$||@.
-}
-- | Sequential function application. The argument is evaluated using
-- the given strategy before it is given to the function.
($|) :: (a -> b) -> Strategy a -> a -> b
f $| s = \ x -> let z = x `using` s in z `pseq` f z
-- | Parallel function application. The argument is evaluated using
-- the given strategy, in parallel with the function application.
($||) :: (a -> b) -> Strategy a -> a -> b
f $|| s = \ x -> let z = x `using` s in z `par` f z但他们有三个论点。我没有看到使用这些操作符的例子,所以我需要想出一个很好的风格来编写它们。
他们通常的风格是:
f $|| strategy $ expr发布于 2015-05-07 21:43:04
优先级与$
所以Haskell有一个非常规则的语法。最优先的是括号,然后是将函数应用于其参数。函数应用程序是左关联的,或者,我更喜欢称之为贪婪的nom:这意味着一个函数“吞噬”了它在它之后看到的作为它的参数的第一件事。因此,如果您编写f g h,这将变成(f g) h:f首先吃g,然后返回值会吃掉h。通常,特别是在定义函数时,您希望编写类似于f (Constructor parameter1 parameter2) = ...的东西,其中确实需要显式括号,这样就不会意外地编写((f Constructor) parameter1) parameter2。
在括号和应用程序之后,我们有运算符:这些操作符具有"infix指令“给出的优先级和关联的整体层次结构。最低优先级操作符被定义为:
f $ g = f g
infixr 0 $这个操作符是一个完全正常的操作符,它似乎什么也不做:更准确地说,它把它左边的函数应用到它右边的参数上。它是低优先级的右关联,所以它是“懒散的nom”( $之前的函数被应用于那个$之后的所有东西)。在f . g . h $ i是否比f $ g $ h $ i更正确或更少的问题上,有一个有趣的语法争议,因为f $ g $ h $ i以不同的方式做了同样的事情。
记住,$实际上只是一个普通的运算符/函数。例如,您可以这样做:
Prelude> let factorial n = product [1..n]
Prelude> map ($ 3) [(5 +), (3 *), (3 +) . factorial . (2 *)]
[8,9,723]这里我们创建了一个函数($ 3),它以一个函数作为它的参数,并将它应用于3。我们将结果函数映射到其他几个函数上。如果您真的需要的话,我们也可以将它编写为zipWith ($) functions (repeat 3),将($)作为组合函数传递给zipWith,zipWith将使用这个函数将两个列表压缩到一起。它们是一样的,它们都是有趣的把戏。甚至有一天,您可能希望对一个值列表进行map (flip ($)),以获得一个函数形式的值列表。这是一个同构;您可以通过id = map ($ id) . map (flip ($))获得值,但也许有一天这种格式会对您更方便。
优先级低于此的是特殊的表单,如if、let、case、do、where和\。通常,Haskell要求这些元素不能立即出现在值或)之后,而是可能出现在(或运算符之后。因此,如果您想编写f \x -> 3 + 2 * x,Haskell会发出抱怨,直到您将其转换为以下内容之一:
f ((3 +) . (2 *)) -- no special forms
f (\x -> 3 + 2 * x) -- parenthesize the sub-expression
f $ \x -> 3 + 2 * x -- use $ to make the syntax "work" effortlessly.类似地,您可能会看到这样的情况:
main = complicatedProcessingStep . preprocessing $ do
input <- io_input
...在这里,$被用来避免在do周围插入括号,这样您就不必在空格中悬挂)令牌。
函数只有一个参数
Haskell与其他语言的一个巨大不同之处在于,每个函数都有一个参数。首先,这可能会让您感到困惑:不是两个参数的操作符函数吗?\a b c -> ...呢,它不是有三个参数吗?
答案是否定的:\a b c -> ...是\a -> \b -> \c -> ...的语法糖(更不用说,您也可以对这些参数进行模式匹配,所以\a -> ...是\random_token -> case random_token of a -> ...的语法糖)。每个函数都有一个参数,但有些函数返回一个函数。在Haskell中,我们可以做其他语言所做的事情,并接受元组;\(a, b) -> a + b工作得很好,相当于uncurry (+)。我们通常不会那样做--我们通常通过\a b -> a + b。
您可以从任何返回函数的函数中生成一个运算符。得到的操作符将其左侧作为第一个函数的参数,其右侧作为对第二个函数的参数。这样做的标准方法是使用backticks:
13 `mod` 7 == mod 13 7但是,如果类型不是多态的,或者如果您编写显式类型签名或禁用“单形限制”,您也可以编写类似于(%%%) = mod的东西。
三参数操作符。
这里有关于“三参数运算符”的答案:它返回一个函数,然后可以应用到其他值中。当你写:
a x $|| b y $ c z由于有了上述规则,本文将其解析为:
($) (($||) (a x) (b y)) (c z)根据($)的定义,它变成:
($||) (a x) (b y) (c z)只需在子表达式ax $|| b y上使用运算符,就会产生一个函数,它可以使用圆括号(如(a x $|| b y) (c z) ),也可以使用$运算符,后者将其左侧应用于其右侧。
https://stackoverflow.com/questions/30099731
复制相似问题