# Reading String into Custom DataType

**URL:** <https://discourse.haskell.org/t/reading-string-into-custom-datatype/4331>\
**Category:** Learn\
**Created:** [April 4, 2022, 9:13pm UTC](https://discourse.haskell.org/t/reading-string-into-custom-datatype/4331 "2022-04-04T21:13:50Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![arstotzka](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/arstotzka/32/2285_2.png) [@arstotzka](https://discourse.haskell.org/u/arstotzka)\
**Post date:** [April 4, 2022, 9:13pm UTC](https://discourse.haskell.org/t/reading-string-into-custom-datatype/4331/1 "2022-04-04T21:13:50Z")

</div>

Suppose we need to store a custom data object into a database and be able to read it back.

```haskell
data Country = USA | MEXICO
instance Show Country where
  show USA = "United States"
  show MEXICO = "Mexico"

```

Suppose after quering a database, we get a string “Mexico”. How to parse it into a Country datatype?

For example, for an integer, I would do the following:

> read “2” :: Int

---

<div class="post-metadata">

**Author:** ![taylorfausak](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/taylorfausak/32/54_2.png) [@taylorfausak](https://discourse.haskell.org/u/taylorfausak)\
**Post date:** [April 4, 2022, 10:41pm UTC](https://discourse.haskell.org/t/reading-string-into-custom-datatype/4331/2 "2022-04-04T22:41:11Z")

</div>

You can implement [the `Read` type class](https://hackage.haskell.org/package/base-4.16.1.0/docs/Text-Read.html#t:Read) for your type. If the exact representation doesn’t matter to you, you can derive these instances:

```haskell
data Country
  = USA
  | Mexico
  deriving (Read, Show)

```

```haskell
>>> show USA
"USA"
>>> read "USA" :: Country
USA

```

---

<div class="post-metadata">

**Author:** ![niko](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/niko/32/2351_2.png) [@niko](https://discourse.haskell.org/u/niko)\
**Post date:** [April 5, 2022, 6:32am UTC](https://discourse.haskell.org/t/reading-string-into-custom-datatype/4331/3 "2022-04-05T06:32:17Z")

</div>

I would not use `read` because it can fail. How about:

```haskell
{-# LANGUAGE OverloadedStrings #-}

import qualified Data.Aeson as Aeson
import Data.Text.Lazy (Text, fromStrict)

toCountry :: Text -> Maybe Country
toCountry text =
  case text of
    "United States" ->
      Just USA
    "Mexico" ->
      Just MEXICO
    _ ->
      Nothing

```

and/or with Aeson:

```haskell
instance Aeson.FromJSON Country where
  parseJSON (Aeson.String s) =
    maybe mempty return (toCountry (fromStrict s))
  parseJSON _ = mempty

```

(I’m very new to haskell, so I could be totally wrong about this)

---

<div class="post-metadata">

**Author:** ![brechtserckx](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/brechtserckx/32/1705_2.png) [@brechtserckx](https://discourse.haskell.org/u/brechtserckx)\
**Post date:** [April 5, 2022, 7:28am UTC](https://discourse.haskell.org/t/reading-string-into-custom-datatype/4331/4 "2022-04-05T07:28:47Z")

</div>

There is a variant that does not throw errors: [`Text.Read.readMaybe`](https://hackage.haskell.org/package/base-4.14.1.0/docs/Text-Read.html#v:readMaybe)

---

<div class="post-metadata">

**Author:** ![tomjaguarpaw](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/tomjaguarpaw/32/1230_2.png) [@tomjaguarpaw](https://discourse.haskell.org/u/tomjaguarpaw)\
**Post date:** [April 5, 2022, 7:41am UTC](https://discourse.haskell.org/t/reading-string-into-custom-datatype/4331/5 "2022-04-05T07:41:01Z")

</div>

Opaleye has exactly this feature by the way:

[https://hackage.haskell.org/package/opaleye-0.9.2.0/docs/Opaleye-Experimental-Enum.html](https://hackage.haskell.org/package/opaleye-0.9.2.0/docs/Opaleye-Experimental-Enum.html)
