我正在尝试使用列表推导来查找列表的中位数,该列表将始终包含具有以下函数的三个整数:
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,所以如果答案非常明显,请原谅我。
答案 0 :(得分:3)
首先,我认为这不会起作用,因为要计算列表的最小和最大 ,您需要使用minimum
和maximum
;不是min
和max
。所以快速解决方法是:
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是在中间)等。