Quais classes de tipo precisam ser definidas para um caminho Yesod?

No meu aplicativo, meu modelo de dados possui várias instâncias diferentes do uso de um inteiro ou de uma string para algum identificador. Por questões de segurança, fui adiante e agrupei esses identificadores em declarações newtype como:

newtype DocId = DocId Integer
newtype GroupName = GroupName String
newtype UserName = UserName String

Quando estou configurando meus caminhos Yesod, estou descobrindo que tenho que criar pelo menos três instâncias para cada uma delas, e as instâncias são quase sempre idênticas

instance Read DocId where
    readsPrec prec val = case reads val of
        (i, ""):_ -> [(DocId i, "")]
        [] -> []

instance B.ToMarkup DocId where
    toMarkup (DocId val) = B.toMarkup val

instance PathPiece DocId where
    toPathPiece (DocId i) = T.pack $ show i
    fromPathPiece s =
        case reads $ T.unpack s of
            (i, ""):_ -> Just i
            [] -> Nothing

Este texto, repetidamente.

O que realmente preciso configurar para renderizar meu tipo de dados em URLs (como @ {ViewDocument docId}) e poder analisar esses URLs?

questionAnswers(2)

yourAnswerToTheQuestion