Précédent   Forum du club des développeurs et IT Pro > Autres langages > Langages fonctionnels > Haskell
Haskell Forum d'entraide sur la programmation en langage fonctionnel Haskell
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 05/07/2010, 14h47   #1
Antoine_935
Membre Expert
 
Avatar de Antoine_935
 
Antoine d'Otreppe
Développeur web/mobile
Inscription : juillet 2006
Messages : 883
Détails du profil
Informations personnelles :
Nom : Antoine d'Otreppe
Localisation : Belgique

Informations professionnelles :
Activité : Développeur web/mobile

Informations forums :
Inscription : juillet 2006
Messages : 883
Points : 1 038
Points : 1 038
Envoyer un message via MSN à Antoine_935
Par défaut Élimination d'un bloc "do" par chainage

Salut, c'est encore moi

Je n'aime pas beaucoup les blocs do, et m'efforce donc de les supprimer.
Sur le coup, j'ai un peu de mal.

Le code avec le do:
Code :
1
2
3
4
5
6
7
8
9
10
import qualified Data.ByteString.Lazy as L

hasElfMagic :: L.ByteString -> Bool
hasElfMagic content = L.take 4 content == elfMagic
    where elfMagic = L.pack [0x7f, 0x45, 0x4c, 0x46]

isElfFile :: FilePath -> IO Bool
isElfFile path = do
  content <- L.readFile path
  return (hasElfMagic content)
Je souhaite donc supprimer le do dans l'action isElfFile.

Ma première idée a été d'utiliser l'opérateur >>=, puis j'ai essayé de chainer les fonctions avec des . (points)
Rien n'y fait, Haskell ne me laissera pas mélanger des actions et des fonctions :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Prelude> :load isElf
[1 of 1] Compiling Main             ( isElf.hs, interpreted )

isElf.hs:8:37:
    Couldn't match expected type `IO Bool' against inferred type `Bool'
    In the second argument of `(>>=)', namely `hasElfMagic'
    In the expression: L.readFile path >>= hasElfMagic
    In the definition of `isElfFile':
        isElfFile path = L.readFile path >>= hasElfMagic
Failed, modules loaded: none.
Prelude> :load isElf
[1 of 1] Compiling Main             ( isElf.hs, interpreted )

isElf.hs:8:26:
    Couldn't match expected type `L.ByteString'
           against inferred type `IO L.ByteString'
    In the second argument of `(.)', namely `L.readFile'
    In the expression: hasElfMagic . L.readFile
    In the definition of `isElfFile':
        isElfFile = hasElfMagic . L.readFile
Failed, modules loaded: none.
J'ai fini par trouver une solution avec une fonction lambda, mais je trouve que c'est beaucoup de bazar pour une petite chose
Code :
isElfFile path = L.readFile path >>= (\contents -> return $ hasElfMagic contents)
Existe-t-il une solution plus concise ?
Antoine_935 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/07/2010, 20h31   #2
dividee
Membre Expert
 
Homme
Inscription : mars 2007
Messages : 851
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : Belgique

Informations forums :
Inscription : mars 2007
Messages : 851
Points : 1 182
Points : 1 182
Citation:
Envoyé par Antoine_935 Voir le message
Existe-t-il une solution plus concise ?
Ceci est plus concis, mais pas forcément plus lisible:
Code :
isElfFile path = L.readFile path >>= return . hasElfMagic
La transformation que tu fais est souvent indentée comme ceci, en écho au bloc do (et ça reste lisible si le bloc est plus long):
Code :
1
2
3
isElfFile path =
        L.readFile path >>= \contents ->
        return $ hasElfMagic contents
dividee est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/07/2010, 20h55   #3
Antoine_935
Membre Expert
 
Avatar de Antoine_935
 
Antoine d'Otreppe
Développeur web/mobile
Inscription : juillet 2006
Messages : 883
Détails du profil
Informations personnelles :
Nom : Antoine d'Otreppe
Localisation : Belgique

Informations professionnelles :
Activité : Développeur web/mobile

Informations forums :
Inscription : juillet 2006
Messages : 883
Points : 1 038
Points : 1 038
Envoyer un message via MSN à Antoine_935
Citation:
Envoyé par dividee Voir le message
Code :
isElfFile path = L.readFile path >>= return . hasElfMagic
Gnarf, j'y étais presque

Je n'avais pas percuté que return était une fonction.
En inversant l'opérateur >>=, on peut arriver à une notation presque point-free.
Code :
1
2
isElfFile :: FilePath -> IO Bool
isElfFile path = return . hasElfMagic =<< L.readFile path
Seulement, dès que je retire le path, c'est la catastrophe
Code :
1
2
3
4
5
6
7
8
9
10
*Main System.FilePath> :load isElf
[1 of 1] Compiling Main             ( isElf.hs, interpreted )

isElf.hs:8:12:
    Couldn't match expected type `IO Bool' against inferred type `Bool'
      Expected type: FilePath -> IO Bool
      Inferred type: FilePath -> Bool
    In the first argument of `(=<<)', namely `return . hasElfMagic'
    In the expression: return . hasElfMagic =<< L.readFile
Failed, modules loaded: none.
Une idée ?


Merci en tout cas pour cette belle réponse


Autre question en passant :
L'opérateur >> existe pour ordonner deux actions.
Existe-t-il l'opérateur inverse << ?*(celui là ne semble pas exister du moins...)
Antoine_935 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/07/2010, 21h31   #4
dividee
Membre Expert
 
Homme
Inscription : mars 2007
Messages : 851
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : Belgique

Informations forums :
Inscription : mars 2007
Messages : 851
Points : 1 182
Points : 1 182
Citation:
Envoyé par Antoine_935 Voir le message
Une idée ?
Code :
1
2
3
4
5
isElfFile = (=<<) (return . hasElfMagic) . L.readFile
-- ou bien
isElfFile = (return . hasElfMagic =<<) . L.readFile
-- ou encore
isElfFile = (>>= return . hasElfMagic) . L.readFile
Mais si tu préfères ça au bloc do, il faut te faire soigner

[EDIT:] pour ton autre question, tu peux toujours écrire:
Code :
1
2
(<<) :: Monad m => m b -> m a -> m b
(<<) = flip (>>)
dividee est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/07/2010, 23h21   #5
Antoine_935
Membre Expert
 
Avatar de Antoine_935
 
Antoine d'Otreppe
Développeur web/mobile
Inscription : juillet 2006
Messages : 883
Détails du profil
Informations personnelles :
Nom : Antoine d'Otreppe
Localisation : Belgique

Informations professionnelles :
Activité : Développeur web/mobile

Informations forums :
Inscription : juillet 2006
Messages : 883
Points : 1 038
Points : 1 038
Envoyer un message via MSN à Antoine_935
Citation:
Envoyé par dividee Voir le message
Mais si tu préfères ça au bloc do, il faut te faire soigner
Haha, probablement

Merci pour ces réponses bien claires
Antoine_935 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/11/2010, 10h24   #6
viro
Nouveau Membre du Club
 
Inscription : octobre 2002
Messages : 36
Détails du profil
Informations personnelles :
Localisation : France

Informations forums :
Inscription : octobre 2002
Messages : 36
Points : 27
Points : 27
Citation:
Envoyé par Antoine_935 Voir le message
Haha, probablement

Merci pour ces réponses bien claires
ce qui est de la forme

Code :
1
2
3
do variable <- action
   return ( fonction variable )
peut généralement se transformer en

Donc là on a :

Code :
is2 p = hasElfMagic `fmap` L.readFile p
Et en pointfree:

Code :
is3 = (hasElfMagic `fmap`) . L.readFile
viro est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Cette discussion est résolue.
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 04h42.


 
 
 
 
Partenaires

Hébergement Web