2013-11-15 40 views
0

我在Haskell工作的形式是在Haskell中爲了它的樂趣而重新工作.Net F#項目。爲什麼不是Haskell部分應用程序工作?

我正在解析一個常規的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

這不是部分應用,而是功能組合不起作用。您不能將2個參數傳遞給作爲函數組成部分的函數。

+0

我想知道它是不是能夠將兩個參數傳遞給作爲函數組合的一部分的函數,但我無法通過簡單的Google搜索找到它。 –

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 -> cg :: c -> d(其中我的意思是說,c s爲在這兩個簽名相同類型的,所以我不會真的在這裏寫適當哈斯克爾簽名)。由於人們經常喜歡將f視爲「兩個變量的函數」,因此可能會錯誤並認爲g . f是函數\x y -> g (f x y)(類型a -> b -> d)。情況並非如此:例如this question and its answersthis answer.的具體示例甚至更好:請看the type of(.)並確定g . f必須是你自己! (提示:Every function takes precisely one argumentf的一個參數是什麼類型?)

+1

看到[這裏](http://meta.stackexchange.com/questions/55437/how-can-the-backtick-character-be-included-in-code)做到這一點:''(p' isPrefixOf ')'' – pat

+0

太好了。謝謝,拍拍。 – gspr

+0

優秀的討論要點!非常感謝你的徹底迴應。 –

相關問題