2013-06-28 17 views
5

Nadal bardzo próbuję dostać się do Haskell, ale zauważyłem, że coś mnie denerwowało.Dlaczego show nie jest traktowane jako konwersja w haskell?

W książce "Learn You a Haskell for Great Good!" jest ta część, która pokazuje użycie strażników w dopasowywaniu wzorców, w przypadku książki była to mała funkcja, która oblicza bmi osoby, poszła trochę coś w tym stylu (części zmienione lekko nie narusza prawa autorskie lub cokolwiek):

bmiCalc :: (RealFloat a) => a -> a -> String 
bmiCalc weight height 
    | bmi <= 18.5 = "skinny" 
    | bmi <= 25.0 = "normal" 
    | bmi <= 30.0 = "fat" 
    | otherwise = "obese" 
    where bmi = weight/height^2 

to wszystko cacy kod działa jak reklamowane, ale pomyślałem, co jeśli to wykazało również, co BMI obliczany był razem z tekstem?

więc ponownie napisał kod do tego:

bmiCalc :: (RealFloat a) => a -> a -> String 
bmiCalc weight height 
    | bmi <= 18.5 = "skinny, " ++ show bmi 
    | bmi <= 25.0 = "normal, " ++ show bmi 
    | bmi <= 30.0 = "fat, " ++ show bmi 
    | otherwise = "obese, " ++ show bmi 
    where bmi = weight/height^2 

Expecting "show" pracować jak .ToString robi w Java i C#
Boy myliłem.

ghci dał mi ten wielki paskudny komunikat o błędzie:

Could not deduce (Show a) arising from a use of `show' 
from the context (RealFloat a) 
    bound by the type signature for 
      bmiCalc :: RealFloat a => a -> a -> String 
    at file.hs:1:16-48 
Possible fix: 
    add (Show a) to the context of 
    the type signature for bmiCalc :: RealFloat a => a -> a -> String 
In the second argument of `(++)', namely `show bmi' 
In the expression: "skinny, " ++ show bmi 
In an equation for `bmiCalc': 
    bmiCalc weight height 
     | bmi <= 18.5 = "skinny, " ++ show bmi 
     | bmi <= 25.0 = "normal, " ++ show bmi 
     | bmi <= 30.0 = "fat, " ++ show bmi 
     | otherwise = "obese, " ++ show bmi 
     where 
      bmi = weight/height^2 
Failed, modules loaded: none. 

dlaczego tak jest? dlaczego nie pozwala mi dołączać do łańcucha znaków czegoś, co wydaje się zwracać ciąg? Chodzi mi o to, że rozumiem, że "skinny, " ++ show bmi jest ciągiem znaków ... co jest dokładnie tym, co sygnatura typu mówi, że muszę zwrócić

więc co zrobiłem źle tutaj?

+1

Czy wypróbowałeś sugestię z komunikatu o błędzie (zaraz po "Możliwe rozwiązanie")? – Yuras

+2

Porównywalny odpowiednik Javy będzie taki, że 'show' jest metodą interfejsu' Show', a twoja wartość 'a' nie jest wymagana do implementacji tego interfejsu, więc istnieje błąd sprawdzania typu podczas kompilacji - to samo działo się w Javie. –

+0

Kiedyś tak było, że typografia "RealFloat" miała 'Show' jako jedno z jego wymagań wstępnych (przez' Num'), ale to się zmieniło nie tak dawno temu. LYAH jest przestarzały pod tym względem (zobacz http://learnyouahaskell.com/types-and-typeclasses#typeclasses-101, wyszukaj "Aby dołączyć Num") – yatima2975

Odpowiedz

9

zmienić podpis typem:

bmiCalc :: (RealFloat a, Show a) => a -> a -> String 

Ponieważ chcesz korzystać z funkcji członka show, od Show typeclass; ale nie określiłeś tego w ograniczeniu funkcji, a ghci nie ma żadnego sposobu, aby wywnioskować, że jest poprawne.

+0

Zabawne jest to, próbowałem zrobić to wcześniej i to nie działa ... jakoś teraz ... dzięki! –

+5

Najłatwiejszym wyjściem, gdy masz takie błędy, jest usunięcie podpisu typu, ponowne załadowanie pliku w ghci i wpisanie ': t bmiCalc'. W ten sposób dodaję wszystkie podpisy mojego typu na końcu. – mhitza

+0

Dobra rada dziękuję! –

2

RealFloat nie jest typem, który można uzyskać. Musisz dodać ograniczenie pokazu.