繁体   English   中英

为什么Haskell部分应用程序不起作用?

[英]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 -> cg :: 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM