无法将预期类型与实际类型匹配

发布于 2024-11-04 07:10:01 字数 896 浏览 3 评论 0原文

我是一个彻头彻尾的 Haskell 菜鸟,我希望有人能帮助我解决这个问题,因为我已经做了几个小时了,我只知道我正在做一些可笑的愚蠢的事情。

该程序应该扫描字典文件,以确定删除了空格的句子集合的所有有效单词序列。

前任。 “insidewaysoften”可以分解为“insidewayoften”、“insidewaysoften”等。

我用 python 编写了我的原型,它工作得很好(我的 Java 实现也是如此),但是该课程需要 Haskell 实现,并且我无法让它工作。为我对语言和 GHC 犯下的罪行提前致歉,代码如下:

import System.Environment   

main = do
  [dictFilename,sentFilename] <- getArgs  
  dictFile <- readFile dictFilename
  sentFile <- readFile sentFilename

  mapM (\sentence -> solve "" "" sentence (words dictFile)) (words sentFile)

solve prefix header [] dict =
  if (header `elem` dict) 
  then return prefix ++ header
  else return ""

solve prefix header sent dict = do
  let more = solve prefix (header ++ (take 1 sent)) (drop 1 sent) dict

  if (header `elem` dict) 
  then return (solve (prefix ++ header ++ " ") "" sent dict) ++ more
  else return more

I am a total Haskell noob and I was hoping someone could help me with this because I've been at this for hours and I just know that I'm doing something ridiculously stupid.

The program is supposed to scan a dictionary file to determine all valid word sequences for a collection of sentences with spaces removed.

Ex. "insidewaysoften" could be broken down to "in side ways often", "inside way soften", etc.

I wrote my prototype in python and it works just fine (as does my Java implementation), but the course requires a Haskell implementation and I cannot get it to work. Apologies in advance for the crimes I have committed against the language and GHC with the following code:

import System.Environment   

main = do
  [dictFilename,sentFilename] <- getArgs  
  dictFile <- readFile dictFilename
  sentFile <- readFile sentFilename

  mapM (\sentence -> solve "" "" sentence (words dictFile)) (words sentFile)

solve prefix header [] dict =
  if (header `elem` dict) 
  then return prefix ++ header
  else return ""

solve prefix header sent dict = do
  let more = solve prefix (header ++ (take 1 sent)) (drop 1 sent) dict

  if (header `elem` dict) 
  then return (solve (prefix ++ header ++ " ") "" sent dict) ++ more
  else return more

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

不回头走下去 2024-11-11 07:10:01

调查类型错误时的第一件事是写下您知道的函数的类型签名。

这里,solve 可能有类型

solve :: String -> String -> String -> [String] -> String

solve :: String -> String -> String -> [String] -> IO String

取决于它在计算值时是否应该有任何副作用。看到您到处使用 mapMreturn,我猜 IO 版本可能是有意为之。

现在,如果您写下签名,您就会开始收到更有意义的错误消息。例如,

tmp.hs:19:16:
    Couldn't match expected type `Char' with actual type `[Char]'
    Expected type: [Char]
      Actual type: [[Char]]
    In the return type of a call of `solve'
    In the first argument of `return', namely
      `(solve (prefix ++ header ++ " ") "" sent dict)'

您得到的不是没有多大意义的:

tmp.hs:14:8:
    Couldn't match expected type `IO String' with actual type `[a0]'
    In the expression: return prefix ++ header
    In the expression:
      if (header `elem` dict) then return prefix ++ header else return ""
    In an equation for `solve':
        solve prefix header [] dict
          = if (header `elem` dict) then
                  return prefix ++ header
            else
                return ""

,它准确地显示了问题所在。函数应用在Haskell中具有最高优先级,因此return prefix ++ header相当于(return prefix)++ header,这绝对不是你的意思。

顺便说一句,如果我从返回类型中删除 IO,删除所有 return 并通过添加 putStrLn 更改调用,代码将编译并且有效!唯一的问题是它将所有可能的句子连接在一起形成一个字符串,没有任何分隔。

The first thing when investigating type errors is to write down the type signatures of functions you know.

Here, solve may have type

solve :: String -> String -> String -> [String] -> String

or

solve :: String -> String -> String -> [String] -> IO String

Depending on whether it should have any side-effects while computing the value. Seeing you using mapM and return all over the place, I guess the IO version may have been intended.

Now, if you write down the signature, you start getting much more meaningful error messages. For example, instead of this:

tmp.hs:19:16:
    Couldn't match expected type `Char' with actual type `[Char]'
    Expected type: [Char]
      Actual type: [[Char]]
    In the return type of a call of `solve'
    In the first argument of `return', namely
      `(solve (prefix ++ header ++ " ") "" sent dict)'

, which does not make much sense, you get this:

tmp.hs:14:8:
    Couldn't match expected type `IO String' with actual type `[a0]'
    In the expression: return prefix ++ header
    In the expression:
      if (header `elem` dict) then return prefix ++ header else return ""
    In an equation for `solve':
        solve prefix header [] dict
          = if (header `elem` dict) then
                  return prefix ++ header
            else
                return ""

,which shows exactly where the problem is. Function application has the highest priority in Haskell, so return prefix ++ header is equivalent to (return prefix) ++ header, which is definitely not what you meant.

By the way, if I remove IO from the return type, remove all the returns and change the invocation by adding putStrLn, the code compiles and works! The only problem is that it concatenates all the possible sentences together into a single string without any delimiting.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文