https://wiki.haskell.org/index.php?title=Wrapper_types&feed=atom&action=historyWrapper types - Revision history2024-03-28T15:29:53ZRevision history for this page on the wikiMediaWiki 1.35.5https://wiki.haskell.org/index.php?title=Wrapper_types&diff=6359&oldid=prevBrettGiles: Links to Phantom Type2006-09-30T15:11:03Z<p>Links to Phantom Type</p>
<table class="diff diff-contentalign-left diff-editfont-monospace" data-mw="interface">
<col class="diff-marker" />
<col class="diff-content" />
<col class="diff-marker" />
<col class="diff-content" />
<tr class="diff-title" lang="en">
<td colspan="2" style="background-color: #fff; color: #202122; text-align: center;">← Older revision</td>
<td colspan="2" style="background-color: #fff; color: #202122; text-align: center;">Revision as of 15:11, 30 September 2006</td>
</tr><tr>
<td colspan="2" class="diff-lineno">Line 1:</td>
<td colspan="2" class="diff-lineno">Line 1:</td>
</tr>
<tr>
<td class="diff-marker">−</td>
<td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div>WrapperTypes are usually trivial wrappers (i.e. newtypes) that are designed to convey some information to the type system. [[Non-trivial type synonyms]] and [[Type class wrapper]] are both instances of this. This idiom is also in a synergistic relation to [[Phantom <del class="diffchange diffchange-inline">types</del>]], [[Traits type class]], and [[Simulating dependent <del class="diffchange diffchange-inline">types</del>]].</div></td>
<td class="diff-marker">+</td>
<td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div>WrapperTypes are usually trivial wrappers (i.e. newtypes) that are designed to convey some information to the type system. [[Non-trivial type synonyms]] and [[Type class wrapper]] are both instances of this. This idiom is also in a synergistic relation to [[Phantom <ins class="diffchange diffchange-inline">type</ins>]], [[Traits type class]], and [[Simulating dependent <ins class="diffchange diffchange-inline">type</ins>]].</div></td>
</tr>
<tr>
<td class="diff-marker"> </td>
<td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"></td>
<td class="diff-marker"> </td>
<td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"></td>
</tr>
<tr>
<td class="diff-marker"> </td>
<td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>==Usages and examples==</div></td>
<td class="diff-marker"> </td>
<td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>==Usages and examples==</div></td>
</tr>
<tr>
<td class="diff-marker">−</td>
<td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div>One use of Wrapper types is to add [[Phantom <del class="diffchange diffchange-inline">types</del>]] to a pre-existing (e.g. 3rd party) type.</div></td>
<td class="diff-marker">+</td>
<td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div>One use of Wrapper types is to add [[Phantom <ins class="diffchange diffchange-inline">type</ins>]] to a pre-existing (e.g. 3rd party) type.</div></td>
</tr>
<tr>
<td class="diff-marker"> </td>
<td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"></td>
<td class="diff-marker"> </td>
<td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"></td>
</tr>
<tr>
<td class="diff-marker"> </td>
<td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>Another example occurs in [[WxHaskell]] to handle interfacing to an OO library. The [[Sub-typing]] relationship is represented as nested wrapper types, so that <hask>type Labrador a = CAnimal (CDog (CLabrador a))</hask> would represent a Labrador or a subclass of it, and <hask>bark :: CAnimal (CDog a) -> IO ()</hask> would be a function that works for any CDog or subclass of it.</div></td>
<td class="diff-marker"> </td>
<td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>Another example occurs in [[WxHaskell]] to handle interfacing to an OO library. The [[Sub-typing]] relationship is represented as nested wrapper types, so that <hask>type Labrador a = CAnimal (CDog (CLabrador a))</hask> would represent a Labrador or a subclass of it, and <hask>bark :: CAnimal (CDog a) -> IO ()</hask> would be a function that works for any CDog or subclass of it.</div></td>
</tr>
<tr>
<td colspan="2" class="diff-lineno">Line 25:</td>
<td colspan="2" class="diff-lineno">Line 25:</td>
</tr>
<tr>
<td class="diff-marker"> </td>
<td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div></haskell></div></td>
<td class="diff-marker"> </td>
<td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div></haskell></div></td>
</tr>
<tr>
<td class="diff-marker"> </td>
<td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"></td>
<td class="diff-marker"> </td>
<td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"></td>
</tr>
<tr>
<td class="diff-marker">−</td>
<td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div>As the example illustrates, the two approaches have different trade-offs, but we can also get some of the benefits of both with the following synergy between [[Phantom <del class="diffchange diffchange-inline">types</del>]] and [[Traits type class]] (and perhaps also wrapper types). What we do is store the traits type variable in a phantom type variable (added in this case via a wrapper type) which avoids the need for a [[Reified type]] parameter or the construction of a custom class (when the class already exists).</div></td>
<td class="diff-marker">+</td>
<td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div>As the example illustrates, the two approaches have different trade-offs, but we can also get some of the benefits of both with the following synergy between [[Phantom <ins class="diffchange diffchange-inline">type</ins>]] and [[Traits type class]] (and perhaps also wrapper types). What we do is store the traits type variable in a phantom type variable (added in this case via a wrapper type) which avoids the need for a [[Reified type]] parameter or the construction of a custom class (when the class already exists).</div></td>
</tr>
<tr>
<td class="diff-marker"> </td>
<td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div><haskell></div></td>
<td class="diff-marker"> </td>
<td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div><haskell></div></td>
</tr>
<tr>
<td class="diff-marker"> </td>
<td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>newtype PString a = PString String</div></td>
<td class="diff-marker"> </td>
<td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>newtype PString a = PString String</div></td>
</tr>
</table>BrettGileshttps://wiki.haskell.org/index.php?title=Wrapper_types&diff=6357&oldid=prevBrettGiles: Convert from HaWiki2006-09-30T15:05:50Z<p>Convert from HaWiki</p>
<p><b>New page</b></p><div>WrapperTypes are usually trivial wrappers (i.e. newtypes) that are designed to convey some information to the type system. [[Non-trivial type synonyms]] and [[Type class wrapper]] are both instances of this. This idiom is also in a synergistic relation to [[Phantom types]], [[Traits type class]], and [[Simulating dependent types]].<br />
<br />
==Usages and examples==<br />
One use of Wrapper types is to add [[Phantom types]] to a pre-existing (e.g. 3rd party) type.<br />
<br />
Another example occurs in [[WxHaskell]] to handle interfacing to an OO library. The [[Sub-typing]] relationship is represented as nested wrapper types, so that <hask>type Labrador a = CAnimal (CDog (CLabrador a))</hask> would represent a Labrador or a subclass of it, and <hask>bark :: CAnimal (CDog a) -> IO ()</hask> would be a function that works for any CDog or subclass of it.<br />
<br />
[[Traits type class]] and wrapper types often give two different approaches to solving the same problem. For example, if you want to compare two Strings for equality in different ways (mainly case-sensitive and case-insensitive) you can either use a wrapper to adapt String to the Eq class,<br />
<haskell><br />
newtype CIString = CIString String<br />
<br />
instance Eq CIString where<br />
CIString a == CIString b = map toUpper a == map toUpper b<br />
</haskell><br />
or you can make a TraitsTypeclass<br />
<haskell><br />
class MyEq traits a where<br />
cmp :: traits -> a -> a -> Bool<br />
<br />
data CaseSensitive<br />
data CaseInsensitive<br />
<br />
instance MyEq CaseSensitive String where cmp _ = (==)<br />
instance MyEq CaseInsensitive String where cmp _ a b = map toUpper a == map toUpper b<br />
</haskell><br />
<br />
As the example illustrates, the two approaches have different trade-offs, but we can also get some of the benefits of both with the following synergy between [[Phantom types]] and [[Traits type class]] (and perhaps also wrapper types). What we do is store the traits type variable in a phantom type variable (added in this case via a wrapper type) which avoids the need for a [[Reified type]] parameter or the construction of a custom class (when the class already exists).<br />
<haskell><br />
newtype PString a = PString String<br />
<br />
data CaseSensitive<br />
data CaseInsensitive<br />
<br />
instance Eq (PString CaseSensitive) where PString a = PString b = a == b<br />
instance Eq (PString CaseInsensitive) where<br />
PString a == PString b = map toUpper a == map toUpper b<br />
</haskell><br />
This gives us the benefit of only having one type that we can parameterize to different implementations and the benefit of working with pre-existing type classes, it does however require us to provide a phantom type argument.<br />
<br />
==See also==<br />
* http://www.haskell.org/pipermail/haskell/2004-August/014397.html gives a rather involved example that uses this idiom.<br />
[[Category:Idioms]]</div>BrettGiles