https://wiki.haskell.org/index.php?title=Concrete_view&feed=atom&action=history
Concrete view - Revision history
2024-03-28T22:31:52Z
Revision history for this page on the wiki
MediaWiki 1.35.5
https://wiki.haskell.org/index.php?title=Concrete_view&diff=18069&oldid=prev
AndrewBromage at 02:22, 4 January 2008
2008-01-04T02:22:14Z
<p></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 02:22, 4 January 2008</td>
</tr><tr>
<td colspan="2" class="diff-lineno">Line 158:</td>
<td colspan="2" class="diff-lineno">Line 158:</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>Remember that Haskell data structures are lazily evaluated. Only as much of the view as the client needs will actually be computed, and if there is any shared work between different parts of the view, it will only be computed once. Accessor functions, by comparison, may do strictly more work than views.</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>Remember that Haskell data structures are lazily evaluated. Only as much of the view as the client needs will actually be computed, and if there is any shared work between different parts of the view, it will only be computed once. Accessor functions, by comparison, may do strictly more work than views.</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;"></td>
<td colspan="2" class="diff-empty"> </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>==Theory==</div></td>
<td colspan="2" class="diff-empty"> </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>==History==</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>==History==</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>[[Views]] were briefly considered as a language extension, but never really caught on. <del class="diffchange diffchange-inline">More</del> <del class="diffchange diffchange-inline">recently,</del> the [[<del class="diffchange diffchange-inline">ViewPattern</del> <del class="diffchange diffchange-inline">proposal</del> <del class="diffchange diffchange-inline">http://hackage.haskell.org/trac/ghc/wiki/ViewPatterns</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>[[Views]] were briefly considered as a language extension, but never really caught on. <ins class="diffchange diffchange-inline">A</ins> <ins class="diffchange diffchange-inline">more recent proposal is</ins> the [[<ins class="diffchange diffchange-inline">View</ins> <ins class="diffchange diffchange-inline">Pattern</ins> <ins class="diffchange diffchange-inline">proposal</ins>]]<ins class="diffchange diffchange-inline">.</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>[[User:AndrewBromage]]</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>[[User:AndrewBromage]]</div></td>
</tr>
</table>
AndrewBromage
https://wiki.haskell.org/index.php?title=Concrete_view&diff=18068&oldid=prev
AndrewBromage at 00:42, 4 January 2008
2008-01-04T00:42:58Z
<p></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 00:42, 4 January 2008</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="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>[[Category:Idioms]]</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>[[Category:Idioms]]</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>It is sometimes not obvious how to implement an operation on some data structure. Using an intermediate [[concrete data type]] can help simplify the case analysis.</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>It is sometimes not obvious how to implement an operation on some data structure. Using an intermediate [[concrete data type]] can help simplify the case analysis.</div></td>
</tr>
<tr>
<td colspan="2" class="diff-empty"> </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;"></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>==Simple example - complex numbers==</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>==Simple example - complex numbers==</div></td>
</tr>
<tr>
<td colspan="2" class="diff-lineno">Line 152:</td>
<td colspan="2" class="diff-lineno">Line 153:</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>==<del class="diffchange diffchange-inline">Summary</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>==<ins class="diffchange diffchange-inline">Efficiency</ins>==</div></td>
</tr>
<tr>
<td colspan="2" class="diff-empty"> </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;"></td>
</tr>
<tr>
<td class="diff-marker"><a class="mw-diff-movedpara-left" title="Paragraph was moved. Click to jump to new location." href="#movedpara_6_2_rhs">⚫</a></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><a name="movedpara_5_0_lhs"></a><del class="diffchange diffchange-inline">If you needed more incentive, remember</del> that Haskell data structures are lazily evaluated. Only as much of the view as the client needs will actually be computed, and if there is any shared work between different parts of the view, it will only be computed once. <del class="diffchange diffchange-inline">You</del> <del class="diffchange diffchange-inline">can't</del> <del class="diffchange diffchange-inline">say</del> <del class="diffchange diffchange-inline">that</del> <del class="diffchange diffchange-inline">about</del> <del class="diffchange diffchange-inline">accessor</del> <del class="diffchange diffchange-inline">functions</del>.</div></td>
<td colspan="2" class="diff-empty"> </td>
</tr>
<tr>
<td colspan="2" class="diff-empty"> </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>View operations are excellent candidates for declaring inline.</div></td>
</tr>
<tr>
<td colspan="2" class="diff-empty"> </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;"></td>
</tr>
<tr>
<td colspan="2" class="diff-empty"> </td>
<td class="diff-marker"><a class="mw-diff-movedpara-right" title="Paragraph was moved. Click to jump to old location." href="#movedpara_5_0_lhs">⚫</a></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><a name="movedpara_6_2_rhs"></a><ins class="diffchange diffchange-inline">Remember</ins> that Haskell data structures are lazily evaluated. Only as much of the view as the client needs will actually be computed, and if there is any shared work between different parts of the view, it will only be computed once. <ins class="diffchange diffchange-inline">Accessor</ins> <ins class="diffchange diffchange-inline">functions,</ins> <ins class="diffchange diffchange-inline">by</ins> <ins class="diffchange diffchange-inline">comparison,</ins> <ins class="diffchange diffchange-inline">may</ins> <ins class="diffchange diffchange-inline">do</ins> <ins class="diffchange diffchange-inline">strictly more work than views</ins>.</div></td>
</tr>
<tr>
<td colspan="2" class="diff-empty"> </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;"></td>
</tr>
<tr>
<td colspan="2" class="diff-empty"> </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>==Theory==</div></td>
</tr>
<tr>
<td colspan="2" class="diff-empty"> </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;"></td>
</tr>
<tr>
<td colspan="2" class="diff-empty"> </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>==History==</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>[[Views]] were briefly considered as a language extension, but never really caught on.</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>[[Views]] were briefly considered as a language extension, but never really caught on.<ins class="diffchange diffchange-inline"> More recently, the [[ViewPattern proposal http://hackage.haskell.org/trac/ghc/wiki/ViewPatterns]]</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>[[User:AndrewBromage]]</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>[[User:AndrewBromage]]</div></td>
</tr>
</table>
AndrewBromage
https://wiki.haskell.org/index.php?title=Concrete_view&diff=11956&oldid=prev
RoelVanDijk: Typo
2007-03-13T23:18:57Z
<p>Typo</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 23:18, 13 March 2007</td>
</tr><tr>
<td colspan="2" class="diff-lineno">Line 2:</td>
<td colspan="2" class="diff-lineno">Line 2:</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>It is sometimes not obvious how to implement an operation on some data structure. Using an intermediate [[concrete data type]] can help simplify the case analysis.</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>It is sometimes not obvious how to implement an operation on some data structure. Using an intermediate [[concrete data type]] can help simplify the case analysis.</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>==<del class="diffchange diffchange-inline">Simlple</del> example - complex numbers==</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>==<ins class="diffchange diffchange-inline">Simple</ins> example - complex numbers==</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>Suppose you're implementing complex numbers (which you wouldn't do, since it's already in the standard library):</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>Suppose you're implementing complex numbers (which you wouldn't do, since it's already in the standard library):</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>
</table>
RoelVanDijk
https://wiki.haskell.org/index.php?title=Concrete_view&diff=9631&oldid=prev
BrettGiles: HaWiki conversion
2006-12-20T22:07:18Z
<p>HaWiki conversion</p>
<p><b>New page</b></p><div>[[Category:Idioms]]<br />
It is sometimes not obvious how to implement an operation on some data structure. Using an intermediate [[concrete data type]] can help simplify the case analysis.<br />
<br />
==Simlple example - complex numbers==<br />
Suppose you're implementing complex numbers (which you wouldn't do, since it's already in the standard library):<br />
<br />
<haskell><br />
data Complex = Complex Double Double<br />
<br />
instance Num Complex where<br />
(Complex r1 i1) + (Complex r2 i2) = Complex (r1+r2) (i1+i2)<br />
{- etc etc -}<br />
</haskell><br />
<br />
Some operations (e.g. complex roots) are easier in polar form. So make a "view" of your complex number type which projects the numbers into polar form:<br />
<br />
<haskell><br />
data ComplexPolarView = ComplexPolarView Double Double<br />
<br />
complexPolarView :: Complex -> ComplexPolarView<br />
complexPolarView (Complex r i) = {- detail omitted -}<br />
<br />
operationThatWouldBeEasierInPolarForm :: Complex -> Something<br />
operationThatWouldBeEasierInPolarForm c<br />
= case complexPolarView c of<br />
ComplexPolarView radius theta -> {- whatever -}<br />
</haskell><br />
<br />
==Use as a design tool==<br />
The technique is also valuable as a design tool. While trying to work out how a data type should be implemented, appropriate use of concrete views can help streamline the design process.<br />
<br />
A good example of this is due to [[User:RalfHinze]] in his paper, [http://www.informatik.uni-bonn.de/~ralf/publications/SearchTree.ps.gz A fresh look at binary search trees]. He notes that binary search tree deletion is much more difficult than insertion. His solution is to use a concrete view of the tree which simplifies the operation, and as a result, comes up with a new representation which makes the operation much easier to understand.<br />
<br />
Here is a simple binary search tree type:<br />
<br />
<haskell><br />
data Tree a = Leaf | Branch (Tree a) a (Tree a)<br />
</haskell><br />
<br />
Suppose that we had a view of the binary search tree which looked like this:<br />
<br />
<haskell><br />
data TreeView a<br />
= EmptyTree<br />
| SingletonTree a<br />
| ConsTree (Tree a) (Tree a)<br />
<br />
treeView :: Tree a -> TreeView a<br />
</haskell><br />
<br />
And the following operations:<br />
<br />
<haskell><br />
-- Return the maximum value in the tree<br />
treeMax :: Tree a -> a<br />
<br />
-- These are the "converses" of the TreeView<br />
emptyTree :: Tree a<br />
singletonTree :: a -> Tree a<br />
consTree :: Tree a -> Tree a -> Tree a<br />
</haskell><br />
<br />
(The "converse" operations are basically [[smart constructor]]s.)<br />
<br />
Then you can implement tree insertion like this:<br />
<br />
<haskell><br />
insert :: (Ord a) => a -> Tree a -> Tree a<br />
insert x t<br />
= case treeView t of<br />
EmptyTree -> singletonTree x<br />
SingletonTree a<br />
| x < a -> consTree (singletonTree x) (singletonTree a)<br />
| x == a -> singletonTree x<br />
| x > a -> consTree (singletonTree a) (singletonTree x)<br />
ConsTree l r<br />
| x < treeMax l -> consTree (insert x l) r<br />
| otherwise -> consTree l (insert x r)<br />
</haskell><br />
<br />
And you could implement tree deletion like this:<br />
<br />
<haskell><br />
delete :: (Ord a) => a -> Tree a -> Tree a<br />
delete x t<br />
= case treeView t of<br />
EmptyTree -> emptyTree<br />
SingletonTree a<br />
| x == a -> emptyTree<br />
| otherwise -> singletonTree a<br />
ConsTree l r<br />
| x <= treeMax l -> consTree (delete x l) r<br />
| otherwise -> consTree l (delete x r)<br />
</haskell><br />
<br />
<br />
Implementing the view and the operations in terms of <hask>Tree</hask> is straightforward, and it allows you to start with a simple data structure and make it more sophisticated as needed. With the view, you can change the implementation of <hask>Tree</hask> without the algorithms changing. Basically, you're using an [[abstract data type]] within a module at the micro-design level.<br />
<br />
Once the algorithms have stabilised, then you can change your implementation (here of <hask>Tree</hask>) to be optimised for the view and operations and refactor out the abstraction layer if you want.<br />
<br />
In this case, redesigning the data structure is simple. Simply pull the maximum element out to the top level:<br />
<br />
<haskell><br />
data Tree a<br />
= Empty<br />
| NonEmpty (Tree' a) a<br />
<br />
data Tree' a<br />
= Leaf<br />
| Branch (Tree' a) a (Tree' a)<br />
<br />
treeView :: Tree a -> TreeView a<br />
treeView Empty = EmptyTree<br />
treeView (NonEmpty Leaf a) = SingletonTree a<br />
treeView (NonEmpty (Branch l x r) a) = ConsTree (NonEmpty l x) (NonEmpty r a)<br />
<br />
maxTree :: Tree a -> a<br />
maxTree (NonEmpty _ a) = a<br />
<br />
-- Implementing emptyTree, singletonTree and consTree are left as an exercise<br />
</haskell><br />
<br />
The <hask>TreeView</hask> data structure can then be refactored out if desired.<br />
<br />
==As part of a module interface==<br />
Concrete views are also valuable at the module interface level. Rather than providing a number of accessor functions to get data out of some type...<br />
<br />
<haskell><br />
module Complex (<br />
Complex,<br />
-- stuff omitted<br />
radius, theta<br />
) where<br />
<br />
radius :: Complex -> Double<br />
theta :: Complex -> Double<br />
<br />
{- etc etc -}<br />
</haskell><br />
<br />
...provide a concrete view instead.<br />
<br />
<haskell><br />
module Complex (<br />
Complex,<br />
-- stuff omitted<br />
ComplexPolarView(..),<br />
complexPolarView<br />
) where<br />
<br />
{- etc etc -}<br />
</haskell><br />
<br />
==Summary==<br />
If you needed more incentive, remember that Haskell data structures are lazily evaluated. Only as much of the view as the client needs will actually be computed, and if there is any shared work between different parts of the view, it will only be computed once. You can't say that about accessor functions.<br />
<br />
[[Views]] were briefly considered as a language extension, but never really caught on.<br />
<br />
[[User:AndrewBromage]]</div>
BrettGiles