2009-06-09 13 views
8

La fonction montrent en Haskell ne semble pas faire ce qu'il faut:Haskell: Montrer foiré?

Prelude> let str = "stack\n\noverflow" 
Prelude> putStrLn str 
stack 


overflow 
Prelude> show str 
"\"Stack\\n\\n\\noverflow\"" 
Prelude> 

Quand je déclare fonctions, je mets normalement les signatures de type comme Afficher, qui ne traite pas correctement les nouvelles lignes . Je veux qu'il traite \n comme des sauts de ligne, pas littéralement "\n". Quand je change le type à String, les fonctions fonctionnent bien. Mais je dois mettre en œuvre une fonction séparée pour les entiers, flottants, etc., etc.

Par exemple, je peux déclarer une fonction:

foo :: (Show x) => x -> IO() 
foo x = do 
    putStrLn $ show x 

... et l'appeler ainsi:

foo "stack\n\noverflow" 
foo 6 
foo [1..] 

Comment devrais-je obtenir la fonction pour retourner ce qui est attendu? C'est à dire. quelle fonction est similaire à show mais peut renvoyer des chaînes contenant des retours à la ligne?

+1

Pouvez-vous nous donner un cas d'utilisation spécifique de ce? Cela faciliterait la compréhension de votre intention. – Martijn

+0

Vous pouvez simplement ajouter une vérification pour voir si l'entrée est une chaîne, et l'imprimer. L'appariement de motifs est une chose très utile. – Rayne

+1

"show" est juste comme "repr()" dans Python et "inspect" dans Ruby, si vous avez déjà utilisé ces langages. –

Répondre

14

Le contrat de la méthode show dans Haskell est de produire une chaîne qui, lorsqu'elle est évaluée, donne la valeur affichée.

Prelude> let str = "stack\n\noverflow" 
Prelude> putStrLn str 
stack 

overflow 
Prelude> putStrLn (show str) 
"stack\n\noverflow" 
Prelude> 
+2

Juste pour ajouter à cela, la fonction que vous avez décrite est appelée "impression" qui est en fait définie comme ci-dessus impression x = putStrLn (show x) – Phyx

3

show montre la variable comme vous l'avez saisie.

Cela me semble assez régulier.

9

Sons comme vous essayez de simuler une méthode ToString, bien que certains de votre terminologie est un peu déroutant.

Vous pouvez simulez comme ceci:

{-# LANGUAGE UndecidableInstances, OverlappingInstances, 
      FlexibleInstances, TypeSynonymInstances #-} 

class ToString a where 
    toString :: a -> String 

instance ToString String where 
    toString = id 

instance Show a => ToString a where 
    toString = show 

Cependant, comme le montrent les pragmas de la langue, ce n'est pas très souhaitable. Pour vraiment avoir une idée de ce que vous essayez de faire, il serait plus facile si nous avions plus de contexte ...

1

Je ne suis pas vraiment sûr de ce que vous essayez de faire. Cela aiderait si vous clarifiiez un peu. Show fait ce qu'il est censé faire. Show produit simplement une chaîne contenant ce qui a été montré.

1

Le plan de Porges fonctionne et je pense qu'il fait ressortir ce que show fait vraiment, puisque le comportement confus que vous avez trouvé dans ghci apparaîtra toujours si vous obtenez la fonction d'E/S que vous voulez. Notez que j'ai ajouté une instance pour Char au code de Porges, puisque vous voudriez probablement que cela n'ait pas de guillemets.

{-# LANGUAGE UndecidableInstances, OverlappingInstances, 
     FlexibleInstances, TypeSynonymInstances #-} 
class ToString a where 
    toString :: a -> String 

instance ToString String where 
    toString = id 

instance ToString Char where 
    toString x = [x] 

instance Show a => ToString a where 
    toString = show 

foo :: (ToString a) => a -> IO() 
foo x = do {putStrLn $ toString x} 

puis, dans ghci, regarder ce qui se passe avec foo.show: "dont la fonction est similaire à show mais peut retourner des chaînes contenant des sauts de ligne"

*Main> let str = "stack\n\noverflow" 
*Main> show str 
"\"stack\\n\\noverflow\""  
*Main> putStrLn str 
stack 

overflow 
*Main> putStrLn (show str) 
"stack\n\noverflow" 
*Main> foo str 
stack 

overflow 
*Main> foo (show str) 
"stack\n\noverflow" 
*Main> foo (show (show str)) 
"\"stack\\n\\noverflow\"" 
*Main> let newl = "\n" 
*Main> foo newl 


*Main> putStrLn newl 


*Main> putStrLn (show newl) 
"\n" 



*Main> foo (show newl) 
"\n" 
*Main> foo (show (show newl)) 
"\"\\n\"" 
*Main> 
0

Réponse: id

+0

Etes-vous juste en train d'essayer d'être drôle ou avez-vous juste notr la question? – Jasper

+0

Ceci est assez ancien, mais peut-être mattiast signifiait 'putStrLn $ id" pile \ n \ noverflow "' qui répond à la question. – stites