Haskell 不确定如何使用`$`函数
当我试图编写一个函数来转换列表列表时,我看到了一些非常奇怪的东西。我试过:Haskell 不确定如何使用`$`函数,haskell,operators,brackets,Haskell,Operators,Brackets,当我试图编写一个函数来转换列表列表时,我看到了一些非常奇怪的东西。我试过: > let abc xs | null (head xs) = [] | otherwise = map head xs : abc $ map tail xs 我犯了一个错误。然后我试着: > let abc xs | null (head xs) = [] | otherwise = map head xs : abc ( map tail xs ) > abc [[1,2,3], [4,5,6]
> let abc xs | null (head xs) = [] | otherwise = map head xs : abc $ map tail xs
我犯了一个错误。然后我试着:
> let abc xs | null (head xs) = [] | otherwise = map head xs : abc ( map tail xs )
> abc [[1,2,3], [4,5,6], [7,8,9]]
[[1,4,7],[2,5,8],[3,6,9]]
我开始相信可以使用
$
操作符来代替括号,这更像是哈斯凯尔式的。为什么会出现错误?运算符是可以应用于中缀位置的函数。因此,$
是一个函数
在Haskell中,您可以定义自己的函数,这些函数可以在参数之间的中缀位置使用。然后,您还可以使用infix
、infixr
、infixl
定义函数应用程序优先级和关联性-也就是说,提示编译器是否将a$b$c
视为(a$b)$c
,或a$(b$c)
$
的优先级使得第一个表达式的解释类似于(映射头xs:abc)$…
例如,要将$
声明为中缀,请将其名称放入()
:
或组成:
(.) :: (b->c)->(a->b)->a->c
(f . g) x = f $ g x
算术“运算符”也被定义为Num类中的中缀函数
此外,您还可以在应用程序站点的backticks``中引用其他函数作为中缀。有时,它会使表达看起来更漂亮:
f `map` xs == map f xs
(并不是说在这种特殊情况下它看起来很漂亮,只是为了展示一个简单的例子)操作符是一个可以应用于中缀位置的函数。因此,
$
是一个函数
在Haskell中,您可以定义自己的函数,这些函数可以在参数之间的中缀位置使用。然后,您还可以使用infix
、infixr
、infixl
定义函数应用程序优先级和关联性-也就是说,提示编译器是否将a$b$c
视为(a$b)$c
,或a$(b$c)
$
的优先级使得第一个表达式的解释类似于(映射头xs:abc)$…
例如,要将$
声明为中缀,请将其名称放入()
:
或组成:
(.) :: (b->c)->(a->b)->a->c
(f . g) x = f $ g x
算术“运算符”也被定义为Num类中的中缀函数
此外,您还可以在应用程序站点的backticks``中引用其他函数作为中缀。有时,它会使表达看起来更漂亮:
f `map` xs == map f xs
(并不是说在这种特殊情况下它看起来很漂亮,只是为了展示一个简单的示例)除了Sassa的正确答案之外,让我们进一步剖析您提供的代码片段:
map head xs : abc $ map tail xs
这里使用两个运算符:(:)
和($)
。如上所述,默认情况下,它们被解释为中缀,因为它们的名称仅由符号组成
每个操作符都有一个优先级,它决定了它绑定的“紧密程度”,或者更有用的是,先应用哪个操作符。您的代码可以解释为
((map head xs) : abc) $ (map tail xs)
其中,(:)
绑定更紧密(以前应用过)($)
或
(map head xs) : (abc $ (map tail xs))
其中,($)
绑定更紧密。请注意,我在函数应用程序周围加了括号(例如map
应用于tail
和xs
)。函数应用程序比任何操作符绑定得更紧密,因此总是首先应用
为了确定这两种解释代码的方法中哪一种是正确的,编译器需要获得关于哪个操作符应该绑定得更紧密的信息。这是使用固定性声明完成的,如
infix 8
或者总体上
infix i
其中i
介于0和9之间。i
的值越高,表示操作符绑定得越紧。(infixr
和infixl
可用于额外定义关联性,如Sassa的回答中所述,但这不会影响您的具体问题。)
事实证明,($)
操作符的固定性声明是
infixr 0 $
如图所示<代码>(:)更“神奇”,因为它是硬编码到Haskell语法中的,但Haskell报告它具有优先级5
现在,我们终于有了足够的信息,可以断定您的代码的第一个解释确实是正确的:(:)
,5的优先级高于($)
,0的优先级。作为一般的经验法则,($)
通常不能与其他操作员很好地交互
顺便说一句,如果一个表达式包含两个具有相同优先级的不同运算符(例如),则它们的应用顺序不清楚,因此必须使用括号明确指定它。除了Sassa的正确答案之外,让我们进一步剖析您提供的代码片段:
map head xs : abc $ map tail xs
这里使用两个运算符:(:)
和($)
。如上所述,默认情况下,它们被解释为中缀,因为它们的名称仅由符号组成
每个操作符都有一个优先级,它决定了它绑定的“紧密程度”,或者更有用的是,先应用哪个操作符。您的代码可以解释为
((map head xs) : abc) $ (map tail xs)
其中,(:)
绑定更紧密(以前应用过)($)
或
(map head xs) : (abc $ (map tail xs))
其中,($)
绑定更紧密。请注意,我在函数应用程序周围加了括号(例如map
应用于tail
和xs
)。函数应用程序比任何操作符绑定得更紧密,因此总是首先应用
为了确定这两种解释代码的方法中哪一种是正确的,编译器需要获得关于哪个操作符应该绑定得更紧密的信息。这是使用固定性声明完成的,如
infix 8
或者总体上
infix i
其中i
介于0和9之间。i
的值越高,表示操作符绑定得越紧。(infixr
和infixl
可用于额外定义关联性,如SASA的回答中所述,但这不会影响您的规范