[英]Why isn't Haskell Partial Application Working?
我在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
谢谢!
它不是部分应用程序,但是功能组合不起作用。 您不能将2个参数传递给作为函数组成部分的函数。
首先要注意的是getLines
的签名。 由于p `isPrefixOf`
类型为(Eq a) => [a] -> Bool
,因此getLines p
类型为(Eq a) => [[a]] -> [[a]]
(基于filter
的类型) 。 这里[a]
似乎是String
,所以getLines p
类型为[String] -> [String]
,因此p
类型似乎为String
。 因此,实际上, getLines
类型为getLines
String -> [String] -> [String]
。
最后, head
具有(专用)类型[String] -> String
,并且您尝试使用getLines
对其进行后getLines
。 我猜想您正在尝试使用\\p ss -> head (getLines p ss)
定义的\\p ss -> head (getLines p ss)
String -> [String] -> String
类型构建函数。 但是,那不是什么head . getLines
head . getLines
是!
要看到这一点,请考虑f :: a -> b -> c
和g :: c -> d
(我的意思是说两个签名中的c
s是同一类型,所以我并不是在写适当的Haskell签名)。 由于人们通常喜欢将f
视为“两个变量的函数”,因此人们可能会犯错并想到g . f
g . f
作为函数\\xy -> g (fxy)
(键入\\xy -> g (fxy)
a -> b -> d
)。 事实并非如此:例如,请参阅此问题及其答案或此答案中的具体示例。 甚至更好:查看(.)
的类型并计算出g . f
g . f
一定是你自己! (提示: 每个函数仅接受一个参数 f
的一个参数的类型是什么?)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.