32 votes

Caractéristiques cachées de Haskell

Ce sont les moins connus, mais utile fonctionnalités du langage de programmation Haskell. (Je comprends la langue elle-même est moins connu, mais travailler avec moi. Même des explications des choses simples en Haskell, comme la définition de la suite de Fibonacci avec une seule ligne de code, sera upvoted par moi.)

  • Essayez de limiter les réponses à la Haskell core
  • Une fonctionnalité pour répondre
  • Donner un exemple et une courte description de la fonction, et pas juste un lien vers la documentation
  • L'étiquette de la fonctionnalité à l'aide titre en gras sur la première ligne

40voto

ephemient Points 87003

Défini par l'utilisateur des structures de contrôle

Haskell n'a pas d'abréviation opérateur ternaire. Le haut- if-then-else est toujours ternaire, et est une expression (impératif langues ont tendance à avoir ?:=expression if=instruction). Si vous voulez, bien que,

True ? x = const x
False ? _ = id

définira (?) à l'opérateur ternaire:

(a ? b $ c)  ==  (if a then b else c)

Vous auriez du avoir recours à des macros dans la plupart des autres langues pour définir votre propre court-circuiter les opérateurs logiques, mais Haskell est un pleinement paresseux de la langue, de sorte qu'il fonctionne, tout simplement.

-- prints "I'm alive! :)"
main = True ? putStrLn "I'm alive! :)" $ error "I'm dead :("

28voto

yairchu Points 9694

Hoogle

Hoogle est votre ami. J'avoue, ça ne fait pas partie de la "base", donc, cabal install hoogle

Maintenant vous savez comment "si vous êtes à la recherche d'une fonction d'ordre supérieur, elle est déjà là" (ephemient du commentaire). Mais comment trouvez-vous cette fonction? Avec hoogle!

$ hoogle "Num a => [a] -> a"
Prelude product :: Num a => [a] -> a
Prelude sum :: Num a => [a] -> a

$ hoogle "[Maybe a] -> [a]"
Data.Maybe catMaybes :: [Maybe a] -> [a]

$ hoogle "Monad m => [m a] -> m [a]"
Prelude sequence :: Monad m => [m a] -> m [a]

$ hoogle "[a] -> [b] -> (a -> b -> c) -> [c]"
Prelude zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]

Le hoogle-google programmeur n'est pas capable d'écrire ses programmes sur le papier par lui-même de la même manière qu'il le fait avec l'aide de l'ordinateur. Mais il et la machine sont obligés de ne pas* à compter avec.

Btw, si vous avez aimé hoogle assurez-vous de vérifier hlint!

25voto

ephemient Points 87003

Mon cerveau vient d'exploser

Si vous essayez de compiler ce code:

{-# LANGUAGE ExistentialQuantification #-}
data Foo = forall a. Foo a
ignorefoo f = 1 where Foo a = f

Vous obtiendrez ce message d'erreur:

$ ghc Foo.hs

Foo.hs:3:22:
 Mon cerveau vient d'exploser.
 Je ne peux pas gérer modèle de liaisons pour existentiellement quantifiés des constructeurs.
 Au lieu de cela, utilisez une expression, ou une notation, pour décompresser le constructeur.
 Dans le groupe de liaison pour
 Foo un
 Dans un modèle de liaison: Foo a = f
 Dans la définition de "ignorefoo':
 ignorefoo f = 1
où
 Toto a = f

22voto

Edward Kmett Points 18369

Gratuit Théorèmes

Phil Wadler nous introduit à la notion de libre théorème et nous avons été en abuser en Haskell depuis.

Ces magnifiques artefacts de Hindley-Milner-type de style de systèmes d'aide général paramétré par un raisonnement par l'aide de parametricity à dire sur ce qu'une fonction ne va pas le faire.

Par exemple, il y a deux lois que chaque instance de Functor doit satisfaire:

  1. forall f g. fmap f . fmap g = fmap f . g)
  2. fmap id = id

Mais, la libre théorème nous dit que nous ne devons pas la peine de prouver la première, mais étant donné le deuxième il s'agit de "libre", il suffit de partir de la signature d'un type de!

fmap :: Functor f => (a -> b) -> f a -> f b

Vous devez être un peu prudent avec la paresse, mais c'est partiellement couverts dans le document original, et dans Janis Voigtlaender de l' étude plus récente sur la libre théorèmes en présence d' seq.

20voto

ephemient Points 87003

Abréviation, pour une liste commune de l'opération

Les suivantes sont équivalentes:

concat $ map f list
concatMap f list
list >>= f

Modifier

Depuis, plus de détails ont été demandés...

concat :: [[a]] -> [a]

concat prend une liste de listes et les concatène dans une seule liste.

map :: (a -> b) -> [a] -> [b]

map cartes d'une fonction sur une liste.

concatMap :: (a -> [b]) -> [a] -> [b]

concatMap est équivalent à (.) concat . map: carte d'une fonction sur une liste, et de les enchaîner les résultats.

class Monad m where
    (>>=) :: m a -> (a -> m b) -> m b
    return :: a -> m a

Un Monad a un bind de l'opération, qui s'appelle >>= en Haskell (ou de ses sucrées do-l'équivalent). Liste, aka [], est une Monad. Si l'on substitue [] pour m ci-dessus:

instance Monad [] where
    (>>=) :: [a] -> (a -> [b]) -> [b]
    return :: a -> [a]

Quelle est la chose naturelle pour l' Monad des opérations à faire sur une liste? Nous avons pour satisfaire la monade lois,

return a >>= f           ==  f a
ma >>= (\a -> return a)  ==  ma
(ma >>= f) >>= g         ==  ma >>= (\a -> f a >>= g)

Vous pouvez vérifier que ces lois tenir si nous utilisons la mise en œuvre

instance Monad [] where
    (>>=) = concatMap
    return = (:[])

return a >>= f  ==  [a] >>= f  ==  concatMap f [a]  ==  f a
ma >>= (\a -> return a)  ==  concatMap (\a -> [a]) ma  ==  ma
(ma >>= f) >>= g  ==  concatMap g (concatMap f ma)  ==  concatMap (concatMap g . f) ma  ==  ma >>= (\a -> f a >>= g)

C'est, en fait, le comportement de l' Monad []. Comme une démonstration,

double x = [x,x]
main = do
    print $ map double [1,2,3]
        -- [[1,1],[2,2],[3,3]]
    print . concat $ map double [1,2,3]
        -- [1,1,2,2,3,3]
    print $ concatMap double [1,2,3]
        -- [1,1,2,2,3,3]
    print $ [1,2,3] >>= double
        -- [1,1,2,2,3,3]

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X