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

Bis*_*943 0 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
Run Code Online (Sandbox Code Playgroud)

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

    • 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 )
   | 

                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

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

任何帮助和其他技巧都适用:)

chi*_*chi 8

getLongestLine l r
    | r == []                = return l
    ....
Run Code Online (Sandbox Code Playgroud)

return在这里注入l任何单子,使得其类型为getLongestLine形式

Monad m => something -> something -> m (something)
Run Code Online (Sandbox Code Playgroud)

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

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

确实,后来选择monad是(->) a因为您使用合成

length . words . getLongestLine h t
Run Code Online (Sandbox Code Playgroud)

这导致类型

getLongestLineLength :: [Char] -> a -> Int
Run Code Online (Sandbox Code Playgroud)

具有一个额外的不需要的a参数,并使getLongestLineLength两个参数代替一个参数(第二个参数传递给getLongestLine,并在那里忽略)。

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

该怎么办:

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

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

longestWordLength :: String -> Int
longestWordLength = maximum . map length . words
Run Code Online (Sandbox Code Playgroud)

与您的问题不紧密相关,但一般建议:

  1. 不要使用headtaill==[]。尽可能使用模式匹配而不是防护。
  2. 打开警告-Wall并解决它们。这本来会报告缺少类型sisgnature到getLongestLine,这引起了误解。