【问题标题】:Read list of unknown type from user input Haskell:从用户输入 Haskell 中读取未知类型列表:
【发布时间】:2017-08-05 10:01:58
【问题描述】:

假设我有以下功能:

readList :: IO [Int]
readList = do
  putStrLn "Please enter the list as a string"
  putStrLn "Example: input of '1 2 3 4 5' will map to [1,2,3,4,5]"
  line <- getLine
  return $ map read $ words line

 printNaive :: [Int] -> IO ()                                                                                                                                                         
 printNaive xs = putStrLn "The maximum surpasser count is:" >> putStrLn "0"

 main :: IO ()
 main = readList >>= printNaive

此功能按预期工作。现在假设我打算将此代码扩展为更通用,并将任何类型的东西作为列表读入一行:

readList :: (Read a, Int a) -> IO [a]
readList = do
  putStrLn "Please enter the list as a string"
  putStrLn "Example: input of '1 2 3 4 5' will map to [1,2,3,4,5]"
  line <- getLine
  return $ map read $ words line

 printNaive :: (Eq a) => [a] -> IO ()                                                                                                                                                         
 printNaive xs = putStrLn "The maximum surpasser count is:" >> putStrLn "0"

 main :: IO ()
 main = readList >>= printNaive

这失败了:

 Ambiguous type variable ‘a0’ arising from a use of ‘Lib.readList’
      prevents the constraint ‘(Read a0)’ from being solved.
      Probable fix: use a type annotation to specify what ‘a0’ should be.
      These potential instances exist:
        instance Read Ordering -- Defined in ‘GHC.Read’
        instance Read Integer -- Defined in ‘GHC.Read’
        instance Read a => Read (Maybe a) -- Defined in ‘GHC.Read’
        ...plus 22 others
        ...plus four instances involving out-of-scope types
        (use -fprint-potential-instances to see them all)

我将如何编写这段代码,因为我真的不在乎它是什么类型的东西,只要它符合Eq

另外,假设我想提供一种工具来指定列表将包含的类型。 (通过另一个 getLine 说)。

如何从getLine 中提取类型,然后如何将map read $ words line 中的每个元素转换为该特定类型。

【问题讨论】:

  • 请发布导致此错误的确切代码。在最小化过程中不要走捷径并猜测哪些代码。验证,方法是把它放在一个单独的文件中,并检查它确实给了你预期的错误。
  • 您可能只需从您的函数中删除类型签名,然后使用 ghci 向 ghc 询问最通用的类​​型,加载您的程序并输入 :t readList
  • 编辑问题以包含更多代码,因为原始集实际上并不是一个最小的可重现示例
  • @AbrahamP 您仍然没有成功提供与出现的错误匹配的代码。
  • 根本不可能不关心它是什么类型。

标签: haskell types type-conversion typeclass


【解决方案1】:

你做错了什么在这一行:

readList :: (Read a, Int a) -> IO [a]

您可能希望使用(Read a, Int a) 获得类型a 的类型类约束,这意味着您希望它是可读的并且您希望它是某种整数。

首先你写错了你的约束。在 =&gt; 而不是 -&gt; 之前给出类型类约束。其次Int 不是类型类。也许尝试使用Integral

所以你的类型签名应该是这样的:

readList :: (Read a, Integral a) => IO [a]

编辑: 但是需要注意的是,类型签名中的a 必须在编译时确定。在您问题的第一个示例中,它可以解决,因为printNaive 的类型将a 修复为Int。但是,通常情况并非如此。

【讨论】:

  • 但是字符或自定义类似的东西呢?假设我想要一个可以同时读取的函数:'abcdef' 到 ["a", "b", "c", "d", "e", "f"] 和 '1 2 3 4 5' 到 [" 1”、“2”、“3”、“4”、“5”]
  • 这个答案解决了呈现代码中的语法错误。但是,显示的代码与问题或错误消息不匹配。 @AbrahamP您根本无法读取要在运行时确定的任何类型的数据。类型在编译时必须是静态已知的。
  • @Thomas 你当然是对的。但是在问题的具体代码中,上面的修改仍然可以正常工作。我将编辑答案以包含您的评论。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-02
  • 1970-01-01
  • 1970-01-01
  • 2017-08-07
相关资源
最近更新 更多