Tutorial :What is the correct type declaration for this function?



Question:

The following function will not load:

charName :: a -> String  charName 'a' = "Alpha"  charName 'b' = "Bravo"  charName 'c' = "Charlie"  charName 'd' = "Delta"  charName 'e' = "Echo"  charName 'f' = "Foxtrot"  charName 'g' = "Golf"  charName 'h' = "Hotel"  charName 'i' = "India"  charName 'j' = "Juliet"  charName 'k' = "Kilo"  charName 'l' = "Lima"  charName 'm' = "mike"  charName 'n' = "November"  charName 'o' = "Oscar"  charName 'p' = "Papa"  charName 'q' = "Quebec"  charName 'r' = "Romeo"  charName 's' = "Sierra"  charName 't' = "Tango"  charName 'u' = "Uniform"  charName 'v' = "Victor"  charName 'w' = "Whiskey"  charName 'x' = "X-ray"  charName 'y' = "Yankee"  charName 'z' = "Zulu"  charName 0 = "Zero"  charName 1 = "One"  charName 2 = "Two"  charName 3 = "Three"  charName 4 = "Four"  charName 5 = "Five"  charName 6 = "Six"  charName 7 = "Seven"  charName 8 = "Eight"  charName 9 = "Nine"  charName x = ""  

It gives me the following error:

[1 of 1] Compiling Main ( baby.hs, interpreted )

baby.hs:41:9: Couldn't match expected type a' against inferred typeChar' a' is a rigid type variable bound by the type signature forcharName' at baby.hs:40:12 In the pattern: 'a' In the definition of `charName': charName 'a' = "Alpha"

baby.hs:67:9: No instance for (Num Char) arising from the literal 0' at baby.hs:67:9 Possible fix: add an instance declaration for (Num Char) In the pattern: 0 In the definition ofcharName': charName 0 = "Zero" Failed, modules loaded: none.

Not sure how I can get this to work. Does anybody have any ideas?


Solution:1

With new data type

The simple way to pass either Char or Int as a function argument, is to define a new data type to encapsulate them:

data (Num a) => CharOrNum a = C Char | N a    charName (C 'z') = "Zulu"  charName (N 0) = "Zero"  

Then you can use it like

ghci> charName $ C 'z'  "Zulu"  ghci> charName $ N 0  "Zero"  

With this change the type of charName is (Num t) => CharOrNum t -> [Char].

With new type class

Another way is to define a common type class for both of the argument types, like Show.

class Nameable a where    nameit :: a -> String    instance Nameable Char where    nameit 'z' = "Zulu"    nameit _ = ""    instance Nameable Integer where    nameit 0 = "Zero"    nameit _ = ""  

Then you can use it like this:

ghci> (nameit 0, nameit 'z')  ("Zero","Zulu")  


Solution:2

The types of the argument in the different cases of charName do not match. Sometimes you use a Char (for example 'a') and sometimes you use a number (for example 9).

There is no way you can make this work by just changing the type signature. (Well, there is one way: add an instance Num Char, but that would be a really bad idea).

The only sane way to achieve what you intended to do is change the numbers to Chars (i.e. '0' instead of 0 etc.).


Solution:3

Well, you have to decide on the type of the parameter. Char or Int? charName 'a' to charName 'z' take a Char as a parameter. charName 0 to charName 9 take an Int. and charName x takes ... well, any type.

I'd change charName 0 into charName '0' etc etc and use charName _ = "" to match any other single Char, other than the listed:

...  charName 'y' = "Yankee"  charName 'z' = "Zulu"  charName '0' = "Zero"  ...  charName '9' = "Nine"  charName _ = ""  

With this changes, the function type is: charName :: Char -> String


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »