Haskell 可以用$替换圆括号吗?
我有以下功能:Haskell 可以用$替换圆括号吗?,haskell,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) 数字::Int->[Int] 数字n=转到n[] 去哪里 |num
digits :: Int -> [Int]
digits n = go n []
where go num acc
| num < 10 = num : acc
| otherwise = go (div num 10) (mod num 10 : acc)
数字::Int->[Int]
数字n=转到n[]
去哪里
|num<10=num:acc
|否则=通过(分区编号10)(模块编号10:acc)
是否可以将表达式中的括号替换为$
问题
你不能用$
来做这个。$
的目的是使函数应用程序尽可能轻松地绑定,这与绑定最紧密的普通函数应用程序不同
> :i $
($) :: (a -> b) -> a -> b
infixr 0 $
(一些不相关的东西被移除了…)
这里,infixr
表示操作符是r右关联的,而infixl
表示操作符是left关联的<代码>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
,因此需要右侧的括号
使用哪种解决方案
在我看来,如果您可以使用不带括号的中缀应用程序,请这样做。在任何一侧都有括号的情况下,例如:divnum10`go`(mod num 10:acc)
,仍然可以保证使用中缀。这主要是由于可读性,因为一般读者可能不熟悉&
。这个符号(可能)不是很常用,这就是为什么一般读者对它不是很熟悉(所以我们有一个循环…)
关于$$
我相信Alexey Romanov的操作符,
$$
也很简洁。不幸的是,它遇到了与和相同的问题:不熟悉。希望他的操作符可以及时添加到数据.函数中,也许我们可以扩展我们的工具箱。除了@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
该操作符$$
可以说比&
,nice one=)更简洁。请注意,该算法只要求divMod
,例如go num=case divMod num 10 of(0,r)->[r];(q,r)->r:go q
。然而,这一点是正确的,它涉及到对算法的语义分析,而不是答案所讨论的更广泛、纯粹的语法分析。=)这只是一个额外的注释,而不是对你的答案的评论:)
f $$ x = f x
infixl 0 $$
go $$ div num 10 $$ mod num 10 : acc