【问题标题】:Type error in a min-and-max function最小和最大函数中的类型错误
【发布时间】:2015-10-06 04:34:05
【问题描述】:

我正在做一个 haskell 项目,并且有一个 minmax 函数,它可以获取列表的最小值和最大值,并以元组对的形式返回它们,如下所示:

λ> minmax [1,2,3]
(1,3)
λ> minmax [4,2,5,9]
(2,9)

现在我正在实现一个递归循环的用户输入列表,直到输入取消输入,然后列表完成,然后需要利用我的 minmax 函数,我遇到的问题是它显然不是同一类型完成后的简单列表,因为它会引发类型错误。

minmax :: (Ord a) => [a] -> (a,a)
minmax [] = error "Null"
minmax (x:xs) = (minimum (x:xs), maximum (x:xs))

convertIO :: IO Int
convertIO = do
    line <- getLine
    return (read line :: Int)

minmaxlist :: IO [Int]
minmaxlist = do
    number <- convertIO
    if(number /= 0)
        then (do 
            int_list <- minmaxlist
            return (minmax (number:int_list)))
    else return []

向我抛出了这个特定的错误:

Couldn't match expected type `[Int]' with actual type `(Int, Int)'

虽然整数列表正是我通过 (number:int_list) 传递的内容,但如果我确实将整数列表传递给它,它会返回元组。为什么它在这里向我抛出错误?是不是跟 IO 类型有关系?

【问题讨论】:

    标签: haskell types io typeerror


    【解决方案1】:

    你的想法是个好主意——minmax 和你产生IO [Int] 的方式似乎都是合理的——我只想将minmax 的应用程序从列表生成中全部排除:

    module Main where
    
    minmax :: (Ord a) => [a] -> (a,a)
    minmax [] = error "Null"
    minmax (x:xs) = (minimum (x:xs), maximum (x:xs))
    
    convertIO :: IO Int
    convertIO = do
        line <- getLine
        return (read line :: Int)
    
    ioInts :: IO [Int]
    ioInts = do
        number <-convertIO
        if number /= 0
          then do 
            int_list <- ioInts
            return (number:int_list)
          else return []
    
    minmaxIO :: IO (Int,Int)
    minmaxIO = do
      list <- ioInts
      return $ minmax list
    
    main :: IO ()
    main = do
      val <- minmaxIO
      print val
    

    您可以使用像 (&lt;$&gt;) 这样的运算符使这一切变得更短,但我认为您更喜欢使用 do 表示法

    如你所见,我刚刚添加了另一个IO 计算minmaxIO,它将minmax 应用于ioInts 生成的列表(我从你的minmaxlist 重命名) - 如果基本上仍然是你的其他东西

    【讨论】:

    • 那么在这种情况下,您要将返回的 IO [Int] 类型的列表转换为列表?您能否详细介绍一下您为 minmaxIO 做了哪些明智的选择?
    • 具体是你设置的IO Int类型的列表吗?还是 Int?
    • 没有实际的转换 - 你的函数 convertIO 的类型是 IO Int,所以 number &lt;- convertIO 提取了一个 Int - 修复了这里的所有类型(当然 IntOrd 的一个实例 - 我用 list &lt;- ioInts 拉出的值 list 将具有 [Int] 类型(如果你这样做 x &lt;- yy :: IO a 那么 y 必须是 x :: a
    • 所以按照我的理解,我试图做的事情是不可能的,因为每次调用函数 ioInts 并设置 int_list 它都需要从 Int 列表中获取它,而不是从 (Int, Int) 这是它返回的内容。
    • 是的 - 你的 if 的两个分支上的类型也不会匹配 - 你可以使用 *hack*/trick @SimonH 建议但 IMO 这样更清楚
    【解决方案2】:

    minmaxlist :: IO [Int] 声明 minmaxlist 是一个返回 Int 列表的 IO 操作。但是,它会尝试返回 minmax(在 return (minmax (number:int_list))) 中)的结果,其类型为 (Int, Int)

    那么,您希望minmaxlist 返回什么?

    【讨论】:

    • 调用时 minmax 的结果,类似于 minmax 的类型,我尝试过强制转换它,但它总是给我一个错误,它“期望一个约束,但 IO [Int] 有一种” *' "
    【解决方案3】:

    你非常接近 - 不要使用元组,而是返回一个列表

    minmax :: (Ord a) => [a] -> [a]
    minmax [] = error "Null"
    minmax xs = [minimum xs, maximum xs]
    

    【讨论】:

    • 我必须将其声明为 [Int],因为这是我的列表累积的唯一方式,所以我接近这个错误了吗?
    • 有同样的问题,类型 [Int] 试图返回但要求 ([Int], [Int])
    猜你喜欢
    • 2020-08-09
    • 2022-01-15
    • 2019-01-02
    • 2015-04-20
    • 2011-01-04
    • 1970-01-01
    • 2015-12-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多