首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 ><=和>运算符作为函数参数

<=和>运算符作为函数参数
EN

Stack Overflow用户
提问于 2015-01-05 11:54:41
回答 1查看 162关注 0票数 3

快速排序:

代码语言:javascript
复制
-- First variant:
qsort :: (Ord a) => [a] -> [a]
qsort [] = []
qsort (x:xs) = left x ++ [x] ++ right x 
  where left  n = qsort [m | m <- xs, m <= n]
        right n = qsort [m | m <- xs, m  > n]

-- λ: qsort [10,2,5,3,1,6,7,4,2,3,4,8,9]
-- [1,2,2,3,3,4,4,5,6,7,8,9,10]

我看到leftright函数几乎是相同的。所以我想把它改写得更短一些..。就像这样:

代码语言:javascript
复制
-- Second variant:
qsort' :: (Ord a) => [a] -> [a]
qsort' [] = []
qsort' (x:xs) = (srt <=) ++ [x] ++ (srt >)
  where srt f = qsort' [m | m <- xs, m f x]

但是,当我试图将它加载到ghci中时,会出现错误

代码语言:javascript
复制
λ: :load temp
[1 of 1] Compiling Main             ( temp.hs, interpreted )

temp.hs:34:18:
    Couldn't match expected type `[a]'
                with actual type `(t0 -> [a]) -> Bool'
    Relevant bindings include
      srt :: forall t. t -> [a] (bound at temp.hs:35:9)
      xs :: [a] (bound at temp.hs:34:11)
      x :: a (bound at temp.hs:34:9)
      qsort' :: [a] -> [a] (bound at temp.hs:33:1)
    In the first argument of `(++)', namely `(srt <=)'
    In the expression: (srt <=) ++ [x] ++ (srt >)
    In an equation for qsort':
        qsort' (x : xs)
          = (srt <=) ++ [x] ++ (srt >)
          where
              srt f = qsort' [m | m <- xs, m f x]

temp.hs:34:37:
    Couldn't match expected type `[a]'
                with actual type `(t1 -> [a]) -> Bool'
    Relevant bindings include
      srt :: forall t. t -> [a] (bound at temp.hs:35:9)
      xs :: [a] (bound at temp.hs:34:11)
      x :: a (bound at temp.hs:34:9)
      qsort' :: [a] -> [a] (bound at temp.hs:33:1)
    In the second argument of `(++)', namely `(srt >)'
    In the second argument of `(++)', namely `[x] ++ (srt >)'
    In the expression: (srt <=) ++ [x] ++ (srt >)

temp.hs:35:38:
    Could not deduce (a ~ (t -> a -> Bool))
    from the context (Ord a)
      bound by the type signature for qsort' :: Ord a => [a] -> [a]
      at temp.hs:32:11-31
      `a' is a rigid type variable bound by
          the type signature for qsort' :: Ord a => [a] -> [a]
          at temp.hs:32:11
    Relevant bindings include
      m :: a (bound at temp.hs:35:29)
      f :: t (bound at temp.hs:35:13)
      srt :: t -> [a] (bound at temp.hs:35:9)
      xs :: [a] (bound at temp.hs:34:11)
      x :: a (bound at temp.hs:34:9)
      qsort' :: [a] -> [a] (bound at temp.hs:33:1)
    The function `m' is applied to two arguments,
    but its type `a' has none
    In the expression: m f x
    In a stmt of a list comprehension: m f x
Failed, modules loaded: none.
λ:

我读了错误信息,但我还是不明白原因.

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-01-05 11:59:00

您不应该使用f作为infix。您可以通过将f放在前面并表示括号(<=)之间的函数来解决这个问题。

代码语言:javascript
复制
-- third variant:
qsort' :: (Ord a) => [a] -> [a]
qsort' [] = []
qsort' (x:xs) = (srt (<=)) ++ [x] ++ (srt (>))
  where srt f = qsort' [m | m <- xs, f m x]

这主要是因为您基本上想要做的是调用mx上的 f。现在默认的lambda演算总是先计算左边列出的函数。

Haskell只为操作符提供了一些语法糖:当您编写a+b时,基本上编写的是(+) a b (窗帘后面)。这是Haskell最喜欢的,但是编译器为程序员提供了一些功能。因为编写a*b+c*d比编写(+) ((*) a b) ((*) c d)要容易得多,但是第二个问题实际上是如何用lambda微积分编写这样的东西。

为了将运算符看作函数,将它们写在括号中,因此要获得<=的函数变体,需要编写(<=)

编辑

正如@Jubobs所指出的,您也可以使用infix,但因此需要使用backticks:

代码语言:javascript
复制
-- fourth variant:
qsort' :: (Ord a) => [a] -> [a]
qsort' [] = []
qsort' (x:xs) = (srt (<=)) ++ [x] ++ (srt (>))
  where srt f = qsort' [m | m <- xs, m `f` x]

问题主要是您需要通过f传递您的函数,而<=>不是函数,(<=)(>)是函数。从技术上讲,这个故事有点复杂,但我想在学习基础知识时,这就足够了。

Haskell通过使用backticks读到:

代码语言:javascript
复制
x `f` y

作为:

代码语言:javascript
复制
f x y

(请注意,这并不是完全正确的,因为操作符也具有优先级*+绑定得更紧,但这些更多地是过程的“细节”)。

在操作符上加上括号是一种相反的效果:

代码语言:javascript
复制
x o y

代码语言:javascript
复制
(o) x y

o是一个操作符。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27778999

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档