2009-06-09 14 views
8

pokazać funkcji w Haskell nie wydaje się robić to, co powinien:Haskell: Show spieprzone?

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


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

Kiedy deklarować funkcje, ja normalnie umieścić podpisy typu jak Pokaż, który nie radzi sobie z nowymi liniami poprawnie . Chcę traktować \n jako znaki nowej linii, a nie dosłownie: "\n". Po zmianie typu na String, funkcje działają poprawnie. Ale będę musiał zaimplementować funkcję oddzielna dla liczb całkowitych, pływaków, itp, itd.

na przykład, może zadeklarować funkcję:

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

... i nazwać go w ten sposób:

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

Jak można uzyskać funkcję zwracania tego, co jest oczekiwane? To znaczy. która funkcja jest podobna do show, ale może zwracać ciągi zawierające znaki nowej linii?

+1

Czy możesz podać nam konkretnego przypadku korzystania z tego? To ułatwi zrozumienie twojego zamiaru. – Martijn

+0

Można po prostu dodać czek, aby sprawdzić, czy dane wejściowe jest ciągiem, i po prostu wydrukować. Dopasowywanie wzorców jest bardzo przydatną rzeczą. – Rayne

+1

"show" jest podobne do 'repr()' w Pythonie i 'inspect' w Ruby, jeśli używałeś już tych języków. –

Odpowiedz

14

Kontrakt metody show w Haskell polega na tym, że tworzy łańcuch, który po obliczeniu daje wartość, która została pokazana.

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

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

Po prostu, aby dodać do tego, funkcja, którą opisałeś nazywa się "print", która jest właściwie zdefiniowana tak jak powyższe print x = putStrLn (show x) – Phyx

3

pokazuje zmienną w taki sposób, w jaki została wprowadzona.

Wydaje się całkiem regularne dla mnie.

9

Brzmi jak próbujesz symulować metodę ToString, chociaż niektóre z terminologii jest trochę mylące.

Można symulować to tak:

{-# 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 

Jednak, jak wynika z pragma języka, to nie jest bardzo pożądane. Aby naprawdę poczuć to, co próbujesz zrobić, byłoby łatwiej, gdybyśmy mieli więcej kontekstu ...

1

Nie jestem pewien co do tego, co próbujesz zrobić. Pomogłoby, gdybyś trochę wyjaśnił. Show robi to, co ma robić. Show po prostu tworzy ciąg zawierający to, co pokazano.

1

Plan Porgesa działa i wydaje mi się, że to się wyda, ponieważ to dziwne zachowanie, które znalazłeś w ghci, wciąż będzie się pojawiać, jeśli uzyskasz pożądaną funkcję IO. Zauważ, że dodałem instancję kodu "Char to Porges", ponieważ prawdopodobnie nie chcesz, aby nie zawierały cytatów.

{-# 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} 

następnie w ghci, obserwować, co dzieje się z foo.show: "która funkcja jest podobna do show ale może wrócić ciągi zawierające znaki nowej linii"

*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

Odpowiedź: id

+0

Po prostu starasz się być śmieszne czy po prostu nie dostałeś odpowiedzi na pytanie? – Jasper

+0

To jest dość stary, ale być może matisse oznaczał 'putStrLn $ id" stos \ n \ noverflow "', który odpowiada na pytanie. – stites