• [^] # Re: deux solutions :

    Posté par (site web personnel) . En réponse au message Haskell : simplifier 2 "case" imbriqués. Évalué à 3. Dernière modification le 13 mai 2016 à 21:10.

    Ouch... Désolé d'arriver après la bataille, mais le code haskell dont le but est d'être le plus concis possible me rend fou, c'est illisible, et ça donne une mauvaise réputation à Haskell.

    Voilà ce que j'écrirais (et je trouve ça 100 fois plus lisible, et c'est beaucoup plus facile à faire évoluer, je vais expliquer pourquoi):

    import Text.Parsec.Error (ParseError)
    import Text.CSV (parseCSVFromFile, CSV)
    liftParsed :: IO (Either ParseError a) -> IO a
    liftParsed = (=<<) $ either (error . show) return
    computation :: CSV -> CSV -> String
    computation = undefined -- Ton code ici
    main :: IO ()
    main = do
     cps <- liftParsed $ parseCSVFromFile "laposte_hexasmal.csv"
     listing <- liftParsed $ parseCSVFromFile "listing.csv"
     putStrLn $ computation cps listing

    Pourquoi c'est plus lisible (ÀMHA)

    La magie est cachée dans liftParsed. L'implémentation de liftParsed est un peu complexe et difficile a lire. Mais tu n'as pas besoin de t'en préoccuper, la seule chose que tu as à lire c'est le type liftParsed :: IO (Either ParseError a) -> IO a.

    Deuxième chose que j'ai modifié c'est le fameux putStrLn . f cps $ listing. Je l'ai remplacé par putStrLn $ f cps listing. « Pourquoi ? » vas-tu me demander. Ce qui important c'est de pouvoir nommer les choses, le $ remplace les parenthèses. Ce qui veux dire que ton expression serait: (putStrLn . f cps) listing, la mienne putStrLn (f cps listing). Les deux fonctionnent, mais pour un lecteur, pour pouvoir comprendre le code, les humains essaient de comprendre ce que les expressions entre parenthèses veulent dire. Une manière de rendre le code plus lisible, serait de donner un nom aux choses entre parenthèse (ce n'est pas toujours nécessaire).

    Dans mon cas je peux écrire:

    let output = f a b in
    putStrLn output

    Dans ton cas, j'ai vraiment du mal a nommer la variable:

    let ???? = putStrLn . f cps in
    ???? listing

    Pourquoi c'est plus facile à faire évoluer?

    Prenons le code de foobarbaz:

    main = (liftM2 . liftM2) f (parseCSVFromFile "laposte_hexasmal.csv") (parseCSVFromFile "listing.csv")
     >>= either (error . show) putStrLn

    Imagine demain tu dois parser 3 fichiers. Voilà comment tu vas le faire évoluer:

    main = (liftM3 . liftM3) f (parseCSVFromFile "laposte_hexasmal.csv") (parseCSVFromFile "listing.csv") (parseCSVFromFile "foo.bar")
     >>= either (error . show) putStrLn

    Je te laisse imaginer le diff avec Git. Et le maximum est liftM5, ça veux dire que tu ne peux pas faire un calcul sur plus de 5 fichiers.

    D'un autre coté avec mon code, voilà le diff avec ma solution:

     main = do
     cps <- liftParsed $ parseCSVFromFile "laposte_hexasmal.csv"
     listing <- liftParsed $ parseCSVFromFile "listing.csv"
    - putStrLn $ computation cps listing
    + other <- liftParsed $ parseCSVFromFile "other.csv"
    + putStrLn $ computation cps listing other

    Edit: J'ai oublié de préciser que le code soumis ici (qui n'est pas celui de foobarbazz) est sous licence WTFPL.