Home > database >  Convert Strings into my own data type with Haskell
Convert Strings into my own data type with Haskell

Time:05-03

I'm working on a Haskell function that is going to to convert a string to a self-defined data type : Position, which should only consist a char of (A-H) and an Int(1-4).(i.e A1, B3, H4)

Here is the function's usage: toPosition gives Just the Position named by the string, or Nothing if the string is not a valid Position name.

Here is my try:

I defined the data type as:

data Position = Pos Char Int

My attempt on toPosition:

import Data.Char
toPosition :: String -> Maybe Position
toPosition string = case string of
  first : second : rest ->
    if isValidChar first
      then if isValidInt second
        then if null rest
          then Just (Pos first (ord second))
          else Nothing -- more than two characters
        else Nothing -- invalid second character
      else Nothing -- invalid first character

isValidChar :: Char -> Bool
isValidChar x
    |x == 'A' = True
    |x == 'B' = True
    |x == 'C' = True
    |x == 'D' = True
    |x == 'E' = True
    |x == 'F' = True
    |x == 'G' = True
    |x == 'H' = True
    |otherwise = False

isValidInt :: Char -> Bool
isValidInt x
    |x == '1' = True
    |x == '2' = True
    |x == '3' = True
    |x == '4' = True
    |otherwise = False

I tried to run it with this in the terminal:

toPosition "H2"

GHCi returning ERROR:

No instance for (Show Position) arising from a use of ‘print’
In a stmt of an interactive GHCi command: print it

Does anyone have ideas about this? Any help would be appreciated!

CodePudding user response:

OK, I've basically got it done.

Just added deriving (Show,Eq) and a anythingElse statement will solve the problem.

Thanks for everyone that helped me!! Love from Italy

CodePudding user response:

The reason this raises an error is because it can not print the Position, since you did not make it an instance of Show. You thus can implement this as:

data Position = Pos Char Int deriving Show

But your functions are also quite complicated. You can simplify isValidChar and isValidInt with:

isValidChar :: Char -> Bool
isValidChar x = 'A' <= x && x <= 'H'

isValidInt :: Char -> Bool
isValidInt x = '1' <= x && x <= '4'

For the toPosition function, you can use pattern matching on a list, since a String is a list of Chars:

import Data.Char(digitToInt)

toPosition :: String -> Maybe Position
toPosition [c, n]
    | isValidChar c && isValidInt n = Just (Position c (digitToInt n))
toPosition _ = Nothing
  • Related