我在Haskell的工作是在Haskell中重新编写.Net F#项目,以获得乐趣。
我正在解析常规Windows配置文件 - 每行一个键/值对,键与值=
分开。这个文件非常简单直接,这使我的解析代码简单直接,我喜欢。
我的问题是为什么部分应用程序不能在下面的最后一行代码上工作。它显然在先前的行和其他功能中工作。
module Configuration (Config (..), load) where
import Data.Char (isSpace)
import Data.List (isPrefixOf)
data Config = Config { aliases :: [String]
, headers :: [String] }
-- This is a naive implementation. I can't decide if I like it better than
-- trim = unpack . strip . pack.
trim :: String -> String
trim = reverse . dropSpaces . reverse . dropSpaces
dropSpaces :: String -> String
dropSpaces = dropWhile isSpace
split _ [] = []
split c cs = [takeWhile (/= c) cs] ++ split c (tail' $ dropWhile (/= c) cs)
where tail' [] = []
tail' (x:xs) = xs
load :: String -> Config
load text =
let ss = lines text
hs = map getValue $ getLines "Header" ss
as = split ',' $ getValue $ getLine "AliasList" ss
in Config { aliases=as, headers=hs }
where getLines p = filter (p `isPrefixOf`)
getValue = trim . drop 1 . dropWhile (/= '=')
getLine = head . getLines -- Why isn't partial application working here?
我得到的错误如下:
Configuration.hs:30:29:
Couldn't match expected type `[c0]'
with actual type `[[a0]] -> [[a0]]'
Expected type: [a0] -> [c0]
Actual type: [a0] -> [[a0]] -> [[a0]]
In the second argument of `(.)', namely `getLines'
In the expression: head . getLines
谢谢!
答案 0 :(得分:2)
不是部分应用,而是功能组合不起作用。您不能将2个参数传递给属于函数组合的函数。
答案 1 :(得分:1)
首先要注意的是getLines
的签名。由于p `isPrefixOf`
的类型为(Eq a) => [a] -> Bool
,getLines p
的类型为(Eq a) => [[a]] -> [[a]]
(基于filter
的类型)。此处[a]
似乎为String
,因此getLines p
的类型为[String] -> [String]
,p
因此似乎具有String
类型。实际上,getLines
的类型为String -> [String] -> [String]
。
最后,head
有(专门)类型[String] -> String
,您尝试使用getLines
进行后期合并。我猜你正在尝试构建一个由String -> [String] -> String
定义的\p ss -> head (getLines p ss)
类型的函数。但是,不 head . getLines
是什么!
要看到这一点,请考虑f :: a -> b -> c
和g :: c -> d
(我的意思是说c
在两个签名中都是相同的类型,所以我并没有真正写出正确的Haskell签名)。由于人们经常喜欢将f
视为“两个变量的函数”,因此可能会错误地将g . f
视为函数\x y -> g (f x y)
(类型a -> b -> d
)。情况并非如此:请参阅this question and its answers或this answer.中的具体示例或更好:查看the type of (.)
并找出g . f
必须的内容做你自己! (提示:Every function takes precisely one argument。f
的一个论点是什么类型?)