如何加入多个函数以应用于文件?哈斯克尔

时间:2017-05-26 18:04:31

标签: haskell types

继续我在haskell的学习,我需要将几个函数应用于文件。我研究并找到了一些提示,但它不起作用,我遇到了类型系统的问题,可以帮助我吗?我做到了:

import Prelude hiding (Word, lines)
import Data.Char
import System.IO
import Data.List hiding (lines)

type Doc = String
type Line = String
type Word = String

makeIndex :: Doc -> [([Int], Word)]
makeIndex = lines . numLines . allNumWords . sortLs . makelists . almalgamate . shorten

lines :: Doc -> [Line]
lines [] = []
lines texto = takeWhile(/='\n') texto:(lines.dropWhile(=='\n').dropWhile(/='\n')) texto

numLines :: [Line] -> [(Int, Line)]
numLines texto = zip [1.. length texto] texto

numWord :: (Int, Line) -> [(Int, Word)]
numWord (number, line) = [(number, word) | word <- divide line]

divide :: String -> [Word]
divide st = split (dropSpace st)

split :: String -> [Word]
split [] = []
split st = (getWord st) : split (dropSpace (dropWord st))

getWord :: String -> String
getWord [] = []
getWord (x:xs) | elem x whitespace = (x:xs)
               | otherwise = dropWord xs

whitespace :: String
whitespace = ['\n', '\t', ' ']

dropSpace :: String -> String
dropSpace [] = []
dropSpace (x:xs) | elem x whitespace = dropSpace xs
                 | otherwise = (x:xs)

dropWord :: String -> String
dropWord [] = []
dropWord (x:xs) | elem x whitespace = (x:xs)
                | otherwise = dropWord xs          

allNumWords :: [(Int, Line)] -> [(Int, Word)]
allNumWords = concat.map numPalavra

sortLs :: [(Int, Word)] -> [(Int, Word)]
sortLs [] = []
sortLs (a:x) = sortLs [b | b <- x, compare b a] ++ [a] ++ sortLs [b | b <- x, compare a b]
                where compare (n1, w1) (n2, w2) = (w1 < w2) || (w1 == w2 && n1 < n2)

makelist :: [(Int, Word)] -> [([Int], Word)]
makelist = map mklis 
             where mklis (num, word) = ([num], word)

almalgamate :: [([Int], Word)] -> [([Int], Word)]
almalgamate [] = []
almalgamate [a] = [a]
almalgamate ((n1, w1) : (n2, w2) : rest) | w1 /= w2 = (n1, w1) : almalgamate ((n2, w2) : rest)
                                         | otherwise = almalgamate ((n1++n2, w1) : rest)

shorten :: [([Int], Word)] -> [([Int], Word)]
shorten = filter long
           where long (num, palavra) = length palavra > 4

在编译器中,错误是:

in line 18
Coldn't match type `[Char]' -> ([Int], Word)'  
Expected type: Doc -> [([Int], Word)]  
Actual type: [([Int], Word] -> [Line]  
int the expression (repeat all the functions)  
in an equation for 'makeIndex' (repeat all the functions)  

makeindex中调用的所有函数都显示相同的错误。

GHCi, version 8.0.1: http://www.haskell.org/ghc/  :? for help
[1 of 1] Compiling Main             ( C:\Users\xxx\Desktop\makeindex.hs, interpreted )

C:\Users\xxx\Desktop\makeindex.hs:17:6: error:  
    * Couldn't match type `[Char]' with `([Int], Word)'  
      Expected type: Doc -> [([Int], Word)]  
        Actual type: [([Int], Word)] -> [String]  
    * In the expression:  
        lines  
        . numLines  
          . allNumWords . sortLs . converte . almalgamate . shorten
      In an equation for `makeIndex':  
          makeIndex  
            = lines  
              . numLines  
                . allNumWords . sortLs . makelist . almalgamate . shorten  

C:\Users\xxx\Desktop\makeindex.hs:18:6: error:  
    * Couldn't match type `(Int, Line)' with `Char'  
      Expected type: [([Int], Word)] -> String  
        Actual type: [([Int], Word)] -> [(Int, Line)]  
    * In the second argument of `(.)', namely  
        `numLines  
         . allNumWords . sortLs . makelist . almalgamate . shorten'
      In the expression:  
        lines  
        . numLines  
          . allNumWords . sortLs . converte . almalgamate . shorten
      In an equation for `makeIndex':  
          makeIndex  
            = lines  
              . numLines  
                . allNumWords . sortLs . makelist . almalgamate . shorten  

C:\Users\xxx\Desktop\makeindex.hs:19:6: error:  
    * Couldn't match type `(Int, Word)' with `[Char]'  
      Expected type: [([Int], Word)] -> [Line]  
        Actual type: [([Int], Word)] -> [(Int, Word)]  
    * In the second argument of `(.)', namely  
        `allNumWords . sortLs . makelist . almalgamate . shorten'  
      In the second argument of `(.)', namely  
        `numLines  
         . allNumWords . sortLs . makelist . almalgamate . shorten'  
      In the expression:  
        lines  
        . numLines  
          . allNumWords . sortLs . makelist . almalgamate . shorten  

C:\Users\xxx\Desktop\makeindex.hs:21:6: error:  
    * Couldn't match type `[Int]' with `Int'  
      Expected type: [([Int], Word)] -> [(Int, Word)]  
        Actual type: [([Int], Word)] -> [([Int], Word)]  
    * In the second argument of `(.)', namely  
        `converte . almalgamate . shorten'  
      In the second argument of `(.)', namely  
        `sortLs . converte . almalgamate . shorten'  
      In the second argument of `(.)', namely  
        `allNumWords . sortLs . makelist . almalgamate . shorten'  

C:\Users\xxx\Desktop\makeindex.hs:22:6: error:  
    * Couldn't match type `[Int]' with `Int'  
      Expected type: [([Int], Word)] -> [(Int, Word)]  
        Actual type: [([Int], Word)] -> [([Int], Word)]  
    * In the second argument of `(.)', namely `almalgamate . shorten'  
      In the second argument of `(.)', namely  
        `converte . almalgamate . shorten'  
      In the second argument of `(.)', namely  
        `sortLs . converte . almalgamate . shorten'  
Failed, modules loaded: none.  

这是问题,匹配类型问题?在第一篇帖子中,我很抱歉对这个问题的描述不好。

1 个答案:

答案 0 :(得分:0)

问题似乎是你把参数的顺序混为(.)。它(基本上)被定义为

(.) :: (b -> c) -> (a -> b) -> a -> c
(f . g) x = f (g x)

首先应用g,然后将f应用于结果。

如果你按照相反的顺序排列函数,你的程序将进行类型检查:

makeIndex = shorten . almalgamate . converte . sortLs
              . allNumWords . numLines . lines

或者,您可以使用(>>>)(.)的翻转版本:

import Control.Category ((>>>))

makeIndex = lines >>> numLines >>> allNumWords >>> sortLs
              >>> converte >>> almalgamate >>> shorten

由于你还没有说出你希望程序做什么,我不能说修改后的版本是否真的正确,但它确实编译