2013-11-15 3 views
0

Моя работа в Haskell происходит в форме повторных работ .Net F # проектов в Haskell для удовольствия.Почему нет частичного применения 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 -> c и g :: c -> d (где я хочу сказать, что c s имеют одинаковый тип в обеих подписей, так что я на самом деле не писать собственные подписи Haskell здесь). Поскольку часто нравится думать о f как о «функции двух переменных», можно подумать, что g . f является функцией \x y -> g (f x y) (тип a -> b -> d). Это не так: см., Например, this question and its answers или конкретный пример в this answer.. Или еще лучше: посмотрите на и выясните, какой g . f должен быть собой! (Подсказка: Every function takes precisely one argument. Что такое один аргумент f?)

+1

Для этого: ['] (http://meta.stackexchange.com/questions/55437/how-can-the-backtick-character-be-included-in-code):' '(p' isPrefixOf ')' ' – pat

+0

Отлично. Спасибо, погладите. – gspr

+0

Отличные точки обсуждения! Большое вам спасибо за тщательный ответ. –

 Смежные вопросы

  • Нет связанных вопросов^_^