Haskell列表理解如何输出一个整数的结果?

时间:2017-02-08 15:58:26

标签: haskell casting list-comprehension

我正在尝试使用列表推导来查找列表的中位数,该列表将始终包含具有以下函数的三个整数:

midNum set = [x | x <- set, x /= maximum set, x /= minimum set]!!0

这可以自行运行,如下例所示:

ghci> midNum [1,2,3]
2

然而,当我尝试将它与我的其他功能结合使用时,它会爆炸,导致以下错误:

*** Exception: Prelude.!!: index too large

当我删除'!! 0'时,编译器会给我这条消息:

Triangle.hs:4:79: error:
* Occurs check: cannot construct the infinite type: t ~ [t]
* In the second argument of `(+)', namely
    `squareOf (midNum triangle)'
  In the second argument of `(==)', namely
    `squareOf (minimum triangle) + squareOf (midNum triangle)'
  In the expression:
    squareOf (maximum triangle)
    == squareOf (minimum triangle) + squareOf (midNum triangle)
* Relevant bindings include
    triangle :: [t] (bound at Triangle.hs:4:9)
    isRight :: [t] -> Bool (bound at Triangle.hs:4:1)
Failed, modules loaded: none.

所以看起来函数给了我一个整数,但编译器期待一个列表。在另一种语言中,我会解决这个问题,但我不确定在Haskell中该怎么做。

这基本上也是我第一次进入Haskell,所以如果答案非常明显,请原谅我。

2 个答案:

答案 0 :(得分:3)

首先,我认为这不会起作用,因为要计算列表的最小最大 ,您需要使用minimummaximum;不是minmax。所以快速解决方法是:

medVal list = [out | out <- list, out /= minimum list, out /= maximum list]
  

当我尝试通过添加&#34;发送函数中的第0个元素时! 0&#34;在函数的末尾,它告诉我这是一个整数的无效操作。

你可以把它写成:

medVal :: Ord a => [a] -> a
medVal list = [out | out <- list, out /= minimum list, out /= maximum list]!!0

或更优雅(也更快):

medVal :: Ord a => [a] -> a
medVal list = head [out | out <- list, out /= minimum list, out /= maximum list]

尽管你肯定知道你会收到三个要素,但我还是不知道使用列表是否是一个好的设计:你可以定义一个带三个参数的函数,或者一个带元素元组的函数。

最后,如果两个或多个元素相同(例如medVal [0,0,20]),您的函数将会出错,因为它会过滤掉所有元素,因此head将找不到一个元素。

答案 1 :(得分:2)

更基本的解决方案

> let midVal x y z | (z>=x)==(x>=y) = x
                   | (x>=y)==(y>=z) = y
                   | otherwise      = z

注意:拼写错误

它来自真值表,但很容易读取线条,例如,如果x小于z且大于y或x大于z且y大于x(因此x是在中间)等。