Question

Mon travail chez Haskell se présente sous la forme de retravailler des projets .Net F# dans Haskell pour le plaisir.

J'analyse un fichier de configuration Windows standard : une paire clé/valeur par ligne, la clé étant séparée de la valeur par =.Ce fichier est très simple et direct, ce qui permet à mon code d'analyse d'être simple et direct, ce que j'aime.

Ma question est de savoir pourquoi l'application partielle ne fonctionne pas sur la dernière ligne de code ci-dessous.Cela fonctionne évidemment dans les lignes précédentes et dans d'autres fonctions.

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?

L'erreur que j'obtiens est la suivante :

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

Merci!

Était-ce utile?

La solution

Ce n’est pas une application partielle, mais une composition fonctionnelle qui ne fonctionne pas.Vous ne pouvez pas transmettre 2 arguments à une fonction qui fait partie d'une composition de fonction.

Autres conseils

La première chose à noter est la signature de getLines.Depuis p `isPrefixOf` a du type (Eq a) => [a] -> Bool, getLines p a du type (Eq a) => [[a]] -> [[a]] (en fonction du type de filter).Ici [a] semble être String, donc getLines p a du type [String] -> [String] et p semble donc avoir le type String.Donc en fait, getLines a du type String -> [String] -> [String].

Dernièrement, head a un type (spécialisé) [String] -> String, et vous essayez de le postcomposer avec getLines.Je suppose que vous essayez de créer une fonction avec le type String -> [String] -> String, Défini par \p ss -> head (getLines p ss).C'est cependant pas quoi head . getLines est!

Pour voir cela, considérez f :: a -> b -> c et g :: c -> d (où je veux dire que le cs sont du même type dans les deux signatures, donc je n'écris pas vraiment de signatures Haskell appropriées ici).Puisqu'on aime souvent penser à f comme une « fonction de deux variables », on pourrait se tromper et penser à g . f comme étant la fonction \x y -> g (f x y) (taper a -> b -> d).Ce n'est pas le cas:Voir par exemple cette question et ses réponses ou l'exemple concret dans cette réponse. Ou encore mieux :Regarder le type de (.) et déterminez quoi g . f ça doit être toi-même !(Indice: Chaque fonction prend précisément un argument.Quel est le type de fc'est un argument ?)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top