为什么我的函数的返回类型是-> Int

时间:2019-06-13 17:41:31

标签: haskell

我在做作业时遇到问题,必须写一个行为类似于wc的程序。 我当前的方法如下:

import qualified Data.ByteString as BS
import qualified Data.ByteString.UTF8 as UTF8

numBytesUtf8 :: String -> Int
numBytesUtf8 = BS.length . UTF8.fromString

help = "Wrong number or wrong arguments provided.\n\
    \Possible arguments are: [l, w, c, b, ll]\n\n\
    \options:\n\
    \    -l  -> Return line count\n\
    \    -w  -> Return word count\n\
    \    -c  -> Return character count\n\
    \    -b  -> Return byte count\n\
    \    -ll -> Return character count of the longest line"

getLongestLine l r
    | r == []                = return l
    | length next > length l = getLongestLine next rest
    | otherwise              = getLongestLine l rest
    where
        next = head r
        rest = tail r

getLongestLineLength :: [Char] -> a -> Int
getLongestLineLength f = length . words . getLongestLine h t
    where
        l = lines f
        h = head l
        t = tail l

handleArgs :: [[Char]] -> [Char] -> IO ()
handleArgs args f
    | head args == "-l"  = print . length . lines $ f
    | head args == "-w"  = print . length . words $ f
    | head args == "-c"  = print . length $ f
    | head args == "-b"  = print . numBytesUtf8 $ f
    | head args == "-ll" = print ( getLongestLineLength f )
    | otherwise = putStrLn help

但是目前我遇到以下错误:

    • No instance for (Show (a0 -> Int)) arising from a use of ‘print’
        (maybe you haven't applied a function to enough arguments?)
    • In the expression: print (getLongestLineLength f)
      In an equation for ‘handleArgs’:
          handleArgs args f
            | head args == "-l" = print . length . lines $ f
            | head args == "-w" = print . length . words $ f
            | head args == "-c" = print . length $ f
            | head args == "-b" = print . numBytesUtf8 $ f
            | head args == "-ll" = print (getLongestLineLength f)
            | otherwise = putStrLn help
   |
43 |     | head args == "-ll" = print ( getLongestLineLength f )
   | 

                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

我对这门语言还是陌生的,直到现在为止我都感到惊讶。但是我不知道如何处理a -> Int,也不知道如何打印它。

使用任何帮助和其他提示:)

1 个答案:

答案 0 :(得分:8)

getLongestLine l r
    | r == []                = return l
    ....

return此处将l注入到任何monad中,从而使getLongestLine的类型具有以下形式

Monad m => something -> something -> m (something)

现在,这是一个事件:您可能不打算这样做。不幸的是,由于您也没有告诉GHC getLongestLine的意图是什么,因此GHC推断了上面的意外类型并继续进行下去,从而在程序后面引起了问题。在getLongestLine上输入类型签名后,您在这里会遇到类型错误。

您真不幸,因为错误的return可能会导致类型错误,但在这种情况下并没有。

实际上,由于您使用合成,后来在monad上被选择为(->) a

length . words . getLongestLine h t

这会导致类型

getLongestLineLength :: [Char] -> a -> Int

有一个多余的a自变量,并使getLongestLineLength接受两个而不是一个参数(第二个参数传递给getLongestLine,并在那里忽略)。

当您最终仅通过一个论点时,GHC最终会抱怨。

做什么:

  1. 除非您正在使用monad,否则不要使用return。使用l代替return l
  2. 始终注释函数的类型,以便GHC可以在出现问题时尽早进行投诉,而不是在推断出意外的类型后再进行投诉。

您的代码中还有其他几个问题,您可能需要进行一些重大更改。我建议您用words早些时候将字符串分割成单词,然后将结果[String]传递给程序的其余部分。不用计算最长的线,而是先计算长度,而是先计算长度,然后取最大值。

longestWordLength :: String -> Int
longestWordLength = maximum . map length . words

与您的问题没有密切关系,但有一般建议:

  1. 请勿使用headtaill==[]。尽可能使用模式匹配而不是防护。
  2. 使用-Wall打开警告并解决它们。这本可以向getLongestLine报告缺少类型的标志,从而引起误解。
相关问题