我有以下功能:
digits :: Int -> [Int]
digits n = go n []
where go num acc
| num < 10 = num : acc
| otherwise = go (div num 10) (mod num 10 : acc)
是否可以将otherwise
表达式中的括号替换为$
?
答案 0 :(得分:8)
您无法使用$
。 $
的目的是使函数应用程序尽可能无法绑定,而不是绑定最紧密的正常函数应用程序,
> :i $
($) :: (a -> b) -> a -> b
infixr 0 $
(删除了一些不相关的东西......)
此处,infixr
表示运算符 r ight关联,而infixl
表示运算符 l eft associative 。 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 &
现在我们得到:
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
go
infix 您还可以使用go
infix:
digits :: Int -> [Int]
digits n = go n []
where go num acc
| num < 10 = num : acc
| otherwise = div num 10 `go` (mod num 10 : acc)
在这种情况下,需要右侧的括号,因为(:)
也是中缀并干扰go
。
在我看来,如果你可以使用没有括号的中缀应用程序,那就这样做吧。如果在任何一侧使用括号,例如:div num 10 `go` (mod num 10 : acc)
,则仍有理由使用中缀。这主要是由于可读性,因为普通读者可能不熟悉&
。这种表示法(可能)不常用,这就是为什么普通读者不熟悉它(因此我们有一个循环......)。
$$
我相信Alexey Romanov的运营商$$
也非常整洁。不幸的是,它遇到了与&
一样的问题:缺乏熟悉感。希望他的运营商可以在适当的时候添加到Data.Function
,也许我们可以扩展我们的工具箱。
答案 1 :(得分:8)
除了@Centril提到的答案之外,你只能替换第二对:
go (div num 10) $ mod num 10 : acc
或两者,但是你需要在不同的地方使用括号:
(go $ div num 10) $ mod num 10 : acc
或声明另一个运算符,如$
但左联合:
f $$ x = f x
infixl 0 $$
go $$ div num 10 $$ mod num 10 : acc