簡體   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