BasicBooties
BasicBooties

Reputation: 31

Haskell: Wont compile with custom datatype

I am a beginner at haskell. Trying to create a program which allows you to enter a string and then manipulate it with different commands.

I've declared a new type called TextEdit which I want to store: -Text left of cursor (l) -Text right of cursor (r) -Text 'selected' by cursor (c) -and a clipboard for copy/cut/pasting (s)

data TextEdit l r c s = TextEdit { left :: l, right :: r, cursor :: c, select :: s }

or

data TextEdit l r c s = TextEdit { left :: [Char], right :: [Char], cursor :: [Char], select :: [Char]}

The rest of my code looks like this so far:

main = do
    putStrLn "-----Text Editor-----" 
    putStrLn "Please enter your text"
    tInput <- getLine
    let tI = TextEdit tInput "|" "" ""
    putStrLn "\n\n" 
    putStrLn tInput


moveCursorLeft :: TextEdit -> TextEdit
moveCursorLeft (TextEdit(l, r, c, s)) = (TextEdit(l, r, c, s))

The user will be calling 'moveCursorLeft tI' to move the cursor.

This is the error I am getting when I try to run it

TextEditor.hs:20:31: error:
* Expecting four more arguments to `TextEdit'
  Expected a type, but `TextEdit' has kind `* -> * -> * -> * -> *'
* In the type signature: moveCursorLeft :: TextEdit -> TextEdit
   |
20 | moveCursorLeft :: TextEdit -> TextEdit
   |                               ^^^^^^^^

Thanks for any help guys :) Really appreciate it

Upvotes: 2

Views: 63

Answers (1)

Thomas M. DuBuisson
Thomas M. DuBuisson

Reputation: 64740

data TextEdit l r c s = TextEdit { left   :: l, right  :: r
                                 , cursor :: c, select :: s }

So TextEdit is a type constructor that takes 4 type arguments, for example TextEdit String String String String would be a valid type. You also have a data constructor of the same name, TextEdit "a" "b" "c" "d" would be a valid value of type TextEdit String String String String.

data TextEdit l r c s = TextEdit { left   :: [Char], right  :: [Char]
                                 , cursor :: [Char], select :: [Char]}

This is somewhat different and probably not what you want. Here TextEdit is still a type constructor but the arguments do not appear on the right hand side - they are phantom. Instead how about you use:

data TextEdit = TextEdit { left   :: [Char], right  :: [Char]
                         , cursor :: [Char], select :: [Char]}

Moving forward we will use this definition. Now TextEdit is NOT a type constructor but it is merely a type.

moveCursorLeft :: TextEdit -> TextEdit
moveCursorLeft (TextEdit(l, r, c, s)) = (TextEdit(l, r, c, s))

Ah no. You have used TextEdit correctly in the main routine but seem to have forgotten what you have learned. TextEdit (l,r,c,s) says the text edit function takes one argument that is a 4-tuple of values. However, looking at the data declaration we know TextEdit takes 4 arguments and they are all [Char] not tuples. So use TextEdit l r c s. Same goes for the function definition, yielding:

moveCursorLeft :: TextEdit -> TextEdit
moveCursorLeft (TextEdit l r c s) = TextEdit l r c s

To restate: (a,b,c,d) is one value - a tuple. F (a,b,c,d) is some constructor F applied to that one value. F a b c d is the constructor F applied to four values. Function application uses spaces and not parenthesis with commas - drop the C syntax.

Upvotes: 3

Related Questions