I'm working on a Haskell school assignment that asks me 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
Then my attempt on toPosition:
toPosition :: String -> Maybe Position
toPosition [] = Nothing
toPosition (x:xs)
| len(xs) == 1 = Loc x xs
| otherwise = Nothing
GHCi returning
'Not in scope: type constructor or class ‘Pos’'
Any ideas to fix this and validate the input so that it will only return a string when the input is a legal 'Position'?
---Update No.1----
I updated my code into the following:
type Position = Pos Char Int
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 (read second :: Int))
else Nothing -- more than two characters
else Nothing -- invalid second character
else Nothing -- invalid first character
isValidChar :: Char -> Bool
isValidChar x
|x == "A" || "B" || "C" || "D" || "E" || "F" || "G" || "H" = True
|otherwise = False
isValidInt :: Char -> Bool
isValidInt x
|x == 1 || 2 || 3 || 4 = True
|otherwise = False
It still gives me error:
Not in scope: type constructor or class ‘Pos’
So I'm wondering how can I represent my self-defined data type so that I don't get any more errors?
CodePudding user response:
Since this is homework I won't provide a complete solution, but hopefully I can give enough to get you unstuck.
You can use pattern matching to get the first and second characters out of the string. Then you can use normal functions to determine if those characters are valid or not. Assuming that they are, you can build a Position
value to return.
data Position = Pos Char Int
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 (charToInt second))
else Nothing -- more than two characters
else Nothing -- invalid second character
else Nothing -- invalid first character
anythingElse -> Nothing -- fewer than two characters
isValidChar :: Char -> Bool
isValidChar = undefined
isValidInt :: Char -> Bool
isValidInt = undefined
charToInt :: Char -> Int
charToInt = undefined