You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
🎯 Target: Python developers willing to understand the context in Haskell of the pandoc metadata type definition:
newtypeMeta=Meta{unMeta::MapTextMetaValue}
The Haskell pattern
It is described for example in Safe Zero-cost Coercions for Haskell under the name of "generative type abstraction". The gist: to represent HTML data for example, we may me tempted to define a type synonym
typeHTML=String
that makes the HTML type undistinguishable from its internal representation. Or instead, in order to get more type safety, we can define a specific wrapper type on top of this representation with
newtypeHTML=HTMLString
Now, a function expecting an instance of HTML won't accept a raw instance of String anymore and some programming errors can be avoided. In order to work with ithe internal representation, we can define a function helper ("deconstructor" or "unwrapper") that would be:
unHTML::HTML->String
unHTML (HTML s) = s
In the Haskell interpreter, using HTML and unHTML would look like this:
> let string = "<body>Pandoc</body>"
> string
"<body>Pandoc</body>"
> let html = HTML string
> html
HTML "<body>Pandoc</body>"
> unHTML html
"<body>Pandoc</body>"
Now, the HTML type and its deconstructor unHTML can be achieved in one declaration instead of two, with the record syntax:
newtypeHTML=HTML{unHTML::String}
which is exactly the pattern that pandoc's Meta is using. Nothing new, just some syntaxic sugar.
At a first glance, we could be tempted to name the wrapped field string - after its type String - instead of unHTML. But you would end up with a deconstructor named with a very generic name string and you wouln't be able to repeat the trick. Say that you have
The, the second deconstructor would shadow the first:
> let html = HTML "<body>pandoc</body>"
> let url = URL "https://pandoc.org"
> let html_string = string html
<interactive>:11:26: error:
• Couldn't match expected type ‘URL’ with actual type ‘HTML’
• In the first argument of ‘string’, namely ‘html’
In the expression: string html
In an equation for ‘html_string’: html_string = string html
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
About the
Meta
type🎯 Target: Python developers willing to understand the context in Haskell of the pandoc metadata type definition:
The Haskell pattern
It is described for example in Safe Zero-cost Coercions for Haskell under the name of "generative type abstraction". The gist: to represent HTML data for example, we may me tempted to define a type synonym
that makes the HTML type undistinguishable from its internal representation. Or instead, in order to get more type safety, we can define a specific wrapper type on top of this representation with
Now, a function expecting an instance of HTML won't accept a raw instance of String anymore and some programming errors can be avoided. In order to work with ithe internal representation, we can define a function helper ("deconstructor" or "unwrapper") that would be:
In the Haskell interpreter, using
HTML
andunHTML
would look like this:Now, the
HTML
type and its deconstructorunHTML
can be achieved in one declaration instead of two, with the record syntax:which is exactly the pattern that pandoc's
Meta
is using. Nothing new, just some syntaxic sugar.At a first glance, we could be tempted to name the wrapped field
string
- after its typeString
- instead ofunHTML
. But you would end up with a deconstructor named with a very generic namestring
and you wouln't be able to repeat the trick. Say that you haveThe, the second deconstructor would shadow the first:
So instead doing
provides systematic deconstructor names that are specific enough to avoid this issue.
How to translate this pattern in Python?
Not that in Python, since field are access with the dot syntax, the previous name collision issue would not exist. We could define
and happily use the field name
string
for both classes.In this context, it's arguably simpler than the "typed unwrapper" scheme.
So it would make sense to translate for example a Haskell typed definition
to
and
to
As long as we have a canonical way to name a field of the wrapped type, we can use it as the named of the wrapper.
(Partial) Conclusion (🚧 wip)
How does this apply to
Meta
, the only use case for this pattern (today) in the pandoc types hierarchy?Well, since
Meta
definition isI think that the Pythonic & systematic thing to do would be to
Map KeyType ValueType
,Map Text MetaValue
,Meta
field.Beta Was this translation helpful? Give feedback.
All reactions