Question

Given the following code:

{-# LANGUAGE OverloadedStrings #-}

newtype Firstname = Firstname String deriving (Eq, Show)
instance IsString Firstname where fromString = Firstname

newtype Lastname = Lastname String deriving (Eq, Show)
instance IsString Lastname where fromString = Lastname

data Person = Person { firstname :: Firstname, lastname :: Lastname, age :: Int } deriving Show

I'd like to remove the boilerplate around creating strongly-typed strings. Is is possible to use Template Haskell (or some other means) to achieve this?

eg something like:

{-# LANGUAGE OverloadedStrings, TemplateHaskell #-}

$(strongString ''Firstname)
$(strongString ''Lastname)

data Person = Person { firstname :: Firstname, lastname :: Lastname, age :: Int } deriving Show
Was it helpful?

Solution

Use GeneralizedNewtypeDeriving and derive the IsString instance for Firstname and Lastname. A sample code for your example follows

{-# LANGUAGE OverloadedStrings, GeneralizedNewtypeDeriving #-}
import Data.String

newtype Firstname = Firstname String deriving (Eq, Show, IsString)

newtype Lastname = Lastname String deriving (Eq, Show, IsString)

data Person = Person { firstname :: Firstname
                     , lastname :: Lastname
                     , age :: Int
                     }

foo = Person "hello" "world" 10

You can use TH to write a similar function which you want but it is not worth the effort while keeping those functions in a separate module and then importing them here.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top