# Create New data types

**URL:** <https://racket.discourse.group/t/create-new-data-types/1911>\
**Category:** Questions & Answers\
**Created:** [May 3, 2023, 6:51am UTC](https://racket.discourse.group/t/create-new-data-types/1911 "2023-05-03T06:51:31Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![mohanr](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/mohanr/32/1059_2.png) [@mohanr](https://racket.discourse.group/u/mohanr)\
**Post date:** [May 3, 2023, 6:51am UTC](https://racket.discourse.group/t/create-new-data-types/1911/1 "2023-05-03T06:51:31Z")

</div>

Hi,  
I tried to port a Haskell data type to racket. Can I create these types ? What is the equivalent racket structure ?

```scheme
(define-struct Error i e ([errorOffset : Offset]
                            [error : ErrorType i e])

```

```scheme
(define-struct ErrorType I e
      ([EndOfInput]
      [Unexpected I]
      [Expected I e]
      [ExpectedEndOfFile I]
      [BeginningOfInput I]
      [Empty])

```

When I split the structure like this it compiles.

```scheme
struct Literal ([i : Char]))
(struct Plus ())
(struct Minus ())
(struct Div ())
(struct InvalidChar ([i : Char]))

```

So if I follow this guideline I get the following code.

```scheme
#lang typed/racket
(require racket/list)

(struct Offset ([Offset : Int]))

(define (operator c )
  (match c
     ['+' Plus]
     ['-' Minus]
     ['/' Div]))

(struct Literal ([i : Char]))
(struct Plus ())
(struct Minus ())
(struct Div ())
(struct InvalidChar ([i : Char]))

(struct: EndOfInput())
(struct: Empty())
(struct: Unexpected([i : Char]))
(struct: Expected([i : Offset] [e : Char]))
(struct: ExpectedEndOfFile([i : Char]))
(struct: BeginningOfInput ([i : Char]))

(define-type (ErrorType i e)
      (U (EndOfInput)
      ( Unexpected i)
      ( Expected i e)
      ( ExpectedEndOfFile i)
      ( BeginningOfInput i)
      ( Empty)))

(define-type (Error i e) (U Offset
                            (ErrorType i e)))

```

which doesn't compile either.

```scheme
/Applications/Racket v8.8/share/pkgs/typed-racket-lib/typed-racket/utils/tc-utils.rkt:57:43: Type Checker: Error in macro expansion -- cannot apply a non-polymorphic type
; type: #(struct:Empty ())
; arguments: ()
; in: here

```

Thanks,  
Mohan

---

<div class="post-metadata">

**Author:** ![hendrikboom3](https://avatars.discourse-cdn.com/v4/letter/h/b5e925/32.png) [@hendrikboom3](https://racket.discourse.group/u/hendrikboom3)\
**Post date:** [May 3, 2023, 12:44pm UTC](https://racket.discourse.group/t/create-new-data-types/1911/2 "2023-05-03T12:44:17Z")

</div>

> Hi,  
> I tried to port a Haskell data type to racket. Can I create these types ? What is the equivalent racket structure ?

What are the Haskell data types you are porting?

---

<div class="post-metadata">

**Author:** ![mohanr](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/mohanr/32/1059_2.png) [@mohanr](https://racket.discourse.group/u/mohanr)\
**Post date:** [May 3, 2023, 1:27pm UTC](https://racket.discourse.group/t/create-new-data-types/1911/3 "2023-05-03T13:27:24Z")

</div>

I am writing a parser and managed to put this Haskell code together mainly by starting with the data structures.

> Haskell

```scheme
data Operator i = Literal i| Plus | Minus | Div
  | InvalidChar I
    deriving (Show, Eq) 

data Error i e = Error
  { errorOffset :: Offset
  , error :: ErrorType I e
  } deriving (Eq, Show)

data ErrorType I e
  = EndOfInput
  | Unexpected I
  | Expected I e
  | ExpectedEndOfFile I
  | BeginningOfInput I
  | Empty
  deriving (Eq, Show)

type Offset = Int

operator :: Char -> Operator Char
operator c | c == '+' = Plus
           | c == '-' = Minus
           | c == '/' = Div
           
scanner :: Offset -> ErrorType Offset Char-> String -> Either [Error Offset (ErrorType Offset Char)] [Operator Char]
scanner offset error (x:xs) 
  | isDigit x = tokenize offset error (Literal x) 
  | x == '+' = tokenize offset error (operator x)
  | otherwise = tokenize offset error (InvalidChar x) 
  where
      tokenize offset error t = 
          case scanner offset error XS of
              Left err -> Left err
              Right tokens -> Right (t : tokens)
scanner offset error "" = Right []

```

I did a similar exercise using racket. Now I started with the same data structures. I managed  
to pass the compiler phase here. I don't see errors but the code is not executed. This is my first racket code. So I  
want to know if this is reasonable code. At this time I don't fully understand the type system since I am just a code monkey.

```scheme
#lang typed/racket
(require racket/list)

(define (operator c )
  (match c
     ['+' Plus]
     ['-' Minus]
     ['/' Div]))

(struct Literal ([i : Char]))
(struct Plus ())
(struct Minus ())
(struct Div ())
(struct InvalidChar ([i : Char]))

(struct EndOfInput())
(struct Empty() )
(struct (i) Unexpected([val : I]))
(define-type (Expected i e) (U Integer Char))
(struct (i) ExpectedEndOfFile([val : I]))
(struct (i) BeginningOfInput ([val : I]))

(define-type (ErrorType I e)
      (U EndOfInput Empty
      ( Unexpected i)
      ( Expected I e)
      ( ExpectedEndOfFile i)
      ( BeginningOfInput i)))
      ;; ( Empty)))

(define-type (Error i e) (U Integer
                            (ErrorType i e)))

```

The Haskell code returns an `Either`. I am trying to understand how this is done using Racket.  
The compiler doesn't accept the commented lines. Error is in original post.  
Thanks.

Update : There is no compiler error as I removed braces around `(Empty)` and `(EndOfInput)`

---

<div class="post-metadata">

**Author:** ![shawnw](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/shawnw/32/1031_2.png) [@shawnw](https://racket.discourse.group/u/shawnw)\
**Post date:** [May 4, 2023, 6:07am UTC](https://racket.discourse.group/t/create-new-data-types/1911/4 "2023-05-04T06:07:51Z")

</div>

Here's a more straightforward translation of part of the Haskell code to Typed Racket to get you started:

```scheme
#lang typed/racket/base

(struct (a) literal ([value : a])
  #:type-name Literal
  #:transparent)

(struct (a) invalid ([value : a])
  #:type-name Invalid
  #:transparent)

(define-type (Operator a) (U (Literal a) 'Plus 'Minus 'Div (Invalid a)))

(: operator : Char -> (Operator Char))
(define (operator ch)
  (case ch
    ((#\+) 'Plus)
    ((#\-) 'Minus)
    ((#\/) 'Div)
    (else (invalid ch))))

```

Note things like the use of symbols instead of structs for many of the values, adding an explicit type signature (Type inference is nice, but in my experience, TR's leaves something to be desired compared to languages like ocaml or haskell), and creating instances of structures instead of trying to return a structure type name like you are doing in your `operator` function

---

<div class="post-metadata">

**Author:** ![mohanr](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/mohanr/32/1059_2.png) [@mohanr](https://racket.discourse.group/u/mohanr)\
**Post date:** [May 4, 2023, 12:57pm UTC](https://racket.discourse.group/t/create-new-data-types/1911/5 "2023-05-04T12:57:32Z")

</div>

Thanks. I am trying to understand this better.

I defined `(define-type (Expected i e) (U Integer Char))`  
so that the complex type with two parameters is accepted. I feel there is a better way.  
How can I declare a 'struct' with two parameters ? Should that be `define-type` ?

```scheme
(define-type (ErrorType i e)
      (U Empty EndOfInput
      ( Unexpected i)
      ( Expected i e)
      ( ExpectedEndOfFile i)
      ( BeginningOfInput i)))

```

Mohan

---

<div class="post-metadata">

**Author:** ![spdegabrielle](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/spdegabrielle/32/95_2.png) [@spdegabrielle](https://racket.discourse.group/u/spdegabrielle)\
**Post date:** [May 8, 2023, 10:26pm UTC](https://racket.discourse.group/t/create-new-data-types/1911/6 "2023-05-08T22:26:39Z")

</div>

Hi Mohan

Saw your question on r/racket and it seemed like it was related to this topic?

I hope my comment there was helpful: [https://www.reddit.com/r/Racket/comments/13bvxtn/parsing\_a\_string\_of\_chars/jje89w5/?utm\_source=share&utm\_medium=ios\_app&utm\_name=ioscss&utm\_content=1&utm\_term=1&context=3](https://www.reddit.com/r/Racket/comments/13bvxtn/parsing_a_string_of_chars/jje89w5/?utm_source=share&utm_medium=ios_app&utm_name=ioscss&utm_content=1&utm_term=1&context=3)

Best regards

Stephen

---

<div class="post-metadata">

**Author:** ![mohanr](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/mohanr/32/1059_2.png) [@mohanr](https://racket.discourse.group/u/mohanr)\
**Post date:** [May 9, 2023, 2:09am UTC](https://racket.discourse.group/t/create-new-data-types/1911/7 "2023-05-09T02:09:51Z")

</div>

Hello,

Yes. I think some video links can be included in the wiki.

1. [https://t.co/ZAXYnUbAzW](https://t.co/ZAXYnUbAzW) , LambdaConf 2015 - Mark Farrell's Introduction to Typed Racket is quite Helpful.

2. Kristopher Micinski's Youtube Racket Videos.

3. Jeremy Siek's Racket compiler book and Indiana University's course link.

Discord is a low-volume forum. I think.

Thanks,  
Mohan
