是否可以用$替换括号?

zer*_*ing 2 haskell

我有以下功能:

digits :: Int -> [Int]
digits n = go n []
    where go num acc
            | num < 10 = num : acc
            | otherwise = go (div num 10) (mod num 10 : acc)
Run Code Online (Sandbox Code Playgroud)

是否可以用otherwise表达式替换括号中的括号$

Cen*_*ril 8

问题

你无法使用$它.目的$是使函数应用程序尽可能无法绑定,而不是绑定最紧密的正常函数应用程序,

> :i $
($) :: (a -> b) -> a -> b
infixr 0 $
Run Code Online (Sandbox Code Playgroud)

(删除了一些不相关的东西......)

这里,infixr表示该操作者是- [R飞行关联,而不是infixl其表示操作者是 EFT关联.0表示运算符的优先级.0束缚最紧密,9束缚最紧密.

如果我们写go $ div num 10 $ mod num 10 : acc,这被解释为go (div num 10 (mod num 10 : acc)),即:mod num 10 : acc作为第三个参数传递div,以及div作为唯一参数应用的结果go.

解决方案:(&)运营商

而不是使用美元符号,$在左侧,您可以改为使用&.

> :i &
(&) :: a -> (a -> b) -> b       -- Defined in `Data.Function'
infixl 1 &
Run Code Online (Sandbox Code Playgroud)

现在我们得到:

import Data.Function ((&))

digits :: Int -> [Int]
digits n = go n []
    where go num acc
            | num < 10 = num : acc
            | otherwise = div num 10 & go $ mod num 10 : acc
Run Code Online (Sandbox Code Playgroud)

解决方案:申请中go

你也可以使用中go缀:

digits :: Int -> [Int]
digits n = go n []
    where go num acc
            | num < 10 = num : acc
            | otherwise = div num 10 `go` (mod num 10 : acc)
Run Code Online (Sandbox Code Playgroud)

在这种情况下,需要右侧的括号,因为(:)它也是中缀和干扰go.

使用哪种解决方案

在我看来,如果你可以使用没有括号的中缀应用程序,那就这样做吧.如果在任何一方使用括号,例如:in div num 10 `go` (mod num 10 : acc),则仍然需要使用中缀.这主要是由于可读性,因为普通读者可能不熟悉&.这种表示法(可能)并不常用,这就是为什么普通读者不熟悉它(因此我们有一个循环......).

论用法 $$

我相信阿列克谢罗曼诺夫的运营商,$$也很整洁.不幸的是,它遇到了同样的问题&:缺乏熟悉度.希望他的操作员可以Data.Function在适当的时候添加,也许我们可以扩展我们的工具箱.


Ale*_*nov 8

除了@Centril提到的答案之外,你只能替换第二对:

go (div num 10) $ mod num 10 : acc
Run Code Online (Sandbox Code Playgroud)

或者两者兼而有之,但是你需要在不同的地方括号:

(go $ div num 10) $ mod num 10 : acc
Run Code Online (Sandbox Code Playgroud)

或声明另一个运算符,$但左关联:

f $$ x = f x
infixl 0 $$

go $$ div num 10 $$ mod num 10 : acc
Run Code Online (Sandbox Code Playgroud)