added doi
This commit is contained in:
49
dist/Coding/Haskell/Advantages.html
vendored
49
dist/Coding/Haskell/Advantages.html
vendored
@ -2,7 +2,7 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="generator" content="quarto-1.7.23">
|
||||
<meta name="generator" content="quarto-1.8.17">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||||
|
||||
@ -33,17 +33,19 @@ ul.task-list li input[type="checkbox"] {
|
||||
<meta name="quarto:offset" content="../../">
|
||||
<script src="../../site_libs/quarto-html/quarto.js" type="module"></script>
|
||||
<script src="../../site_libs/quarto-html/tabsets/tabsets.js" type="module"></script>
|
||||
<script src="../../site_libs/quarto-html/axe/axe-check.js" type="module"></script>
|
||||
<script src="../../site_libs/quarto-html/popper.min.js"></script>
|
||||
<script src="../../site_libs/quarto-html/tippy.umd.min.js"></script>
|
||||
<script src="../../site_libs/quarto-html/anchor.min.js"></script>
|
||||
<link href="../../site_libs/quarto-html/tippy.css" rel="stylesheet">
|
||||
<link href="../../site_libs/quarto-html/quarto-syntax-highlighting-dark-2c84ecb840a13f4c7993f9e5648f0c14.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles">
|
||||
<link href="../../site_libs/quarto-html/quarto-syntax-highlighting-6cf5824034cebd0380a5b9c74c43f006.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles">
|
||||
<link href="../../site_libs/quarto-html/quarto-syntax-highlighting-ff1c8a91a872873ab9706226229f9e30.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles">
|
||||
<link href="../../site_libs/quarto-html/quarto-syntax-highlighting-dark-04b38c9dba5d7c0f1fe2b621b39e7e62.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles">
|
||||
<link href="../../site_libs/quarto-html/quarto-syntax-highlighting-ff1c8a91a872873ab9706226229f9e30.css" rel="stylesheet" class="quarto-color-scheme-extra" id="quarto-text-highlighting-styles">
|
||||
<script src="../../site_libs/bootstrap/bootstrap.min.js"></script>
|
||||
<link href="../../site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
|
||||
<link href="../../site_libs/bootstrap/bootstrap-ec71cb1e120c0dd41819aca960e74e38.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light">
|
||||
<link href="../../site_libs/bootstrap/bootstrap-dark-716ed94a23403968eaa6fe981e0cbf91.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="dark">
|
||||
<link href="../../site_libs/bootstrap/bootstrap-ec71cb1e120c0dd41819aca960e74e38.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme-extra" id="quarto-bootstrap" data-mode="light">
|
||||
<link href="../../site_libs/bootstrap/bootstrap-9b56b6674ace31b1957ea5f5ef42286f.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light">
|
||||
<link href="../../site_libs/bootstrap/bootstrap-dark-3c8015a3c2181875b3e8a350495bd83c.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="dark">
|
||||
<link href="../../site_libs/bootstrap/bootstrap-9b56b6674ace31b1957ea5f5ef42286f.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme-extra" id="quarto-bootstrap" data-mode="light">
|
||||
<script id="quarto-search-options" type="application/json">{
|
||||
"location": "navbar",
|
||||
"copy-button": false,
|
||||
@ -96,7 +98,7 @@ ul.task-list li input[type="checkbox"] {
|
||||
toggleBodyColorMode(bsSheetEl);
|
||||
}
|
||||
}
|
||||
window.setColorSchemeToggle = (alternate) => {
|
||||
const setColorSchemeToggle = (alternate) => {
|
||||
const toggles = window.document.querySelectorAll('.quarto-color-scheme-toggle');
|
||||
for (let i=0; i < toggles.length; i++) {
|
||||
const toggle = toggles[i];
|
||||
@ -129,7 +131,7 @@ ul.task-list li input[type="checkbox"] {
|
||||
}
|
||||
manageTransitions('#quarto-margin-sidebar .nav-link', true);
|
||||
// Switch the toggles
|
||||
window.setColorSchemeToggle(alternate)
|
||||
setColorSchemeToggle(alternate)
|
||||
// Hack to workaround the fact that safari doesn't
|
||||
// properly recolor the scrollbar when toggling (#1455)
|
||||
if (navigator.userAgent.indexOf('Safari') > 0 && navigator.userAgent.indexOf('Chrome') == -1) {
|
||||
@ -169,7 +171,7 @@ ul.task-list li input[type="checkbox"] {
|
||||
const isFileUrl = () => {
|
||||
return window.location.protocol === 'file:';
|
||||
}
|
||||
window.hasAlternateSentinel = () => {
|
||||
const hasAlternateSentinel = () => {
|
||||
let styleSentinel = getColorSchemeSentinel();
|
||||
if (styleSentinel !== null) {
|
||||
return styleSentinel === "alternate";
|
||||
@ -197,7 +199,7 @@ ul.task-list li input[type="checkbox"] {
|
||||
const baseTheme = document.querySelector('#giscus-base-theme')?.value ?? 'light';
|
||||
const alternateTheme = document.querySelector('#giscus-alt-theme')?.value ?? 'dark';
|
||||
let newTheme = '';
|
||||
if(darkModeDefault) {
|
||||
if(authorPrefersDark) {
|
||||
newTheme = isAlternate ? baseTheme : alternateTheme;
|
||||
} else {
|
||||
newTheme = isAlternate ? alternateTheme : baseTheme;
|
||||
@ -220,17 +222,20 @@ ul.task-list li input[type="checkbox"] {
|
||||
changeGiscusTheme();
|
||||
}
|
||||
};
|
||||
const authorPrefersDark = false;
|
||||
const queryPrefersDark = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
const darkModeDefault = queryPrefersDark.matches;
|
||||
document.querySelector('link.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
|
||||
document.querySelector('link#quarto-text-highlighting-styles.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
|
||||
document.querySelector('link#quarto-bootstrap.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
|
||||
let localAlternateSentinel = darkModeDefault ? 'alternate' : 'default';
|
||||
// Dark / light mode switch
|
||||
window.quartoToggleColorScheme = () => {
|
||||
// Read the current dark / light value
|
||||
let toAlternate = !window.hasAlternateSentinel();
|
||||
let toAlternate = !hasAlternateSentinel();
|
||||
toggleColorMode(toAlternate);
|
||||
setStyleSentinel(toAlternate);
|
||||
toggleGiscusIfUsed(toAlternate, darkModeDefault);
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
};
|
||||
queryPrefersDark.addEventListener("change", e => {
|
||||
if(window.localStorage.getItem("quarto-color-scheme") !== null)
|
||||
@ -241,7 +246,7 @@ ul.task-list li input[type="checkbox"] {
|
||||
toggleGiscusIfUsed(alternate, darkModeDefault);
|
||||
});
|
||||
// Switch to dark mode if need be
|
||||
if (window.hasAlternateSentinel()) {
|
||||
if (hasAlternateSentinel()) {
|
||||
toggleColorMode(true);
|
||||
} else {
|
||||
toggleColorMode(false);
|
||||
@ -253,6 +258,8 @@ ul.task-list li input[type="checkbox"] {
|
||||
<nav class="navbar navbar-expand-lg " data-bs-theme="dark">
|
||||
<div class="navbar-container container-fluid">
|
||||
<div class="navbar-brand-container mx-auto">
|
||||
<a href="../../index.html" class="navbar-brand navbar-brand-logo">
|
||||
</a>
|
||||
<a class="navbar-brand" href="../../index.html">
|
||||
<span class="navbar-title">Nicole Dresselhaus</span>
|
||||
</a>
|
||||
@ -264,12 +271,12 @@ ul.task-list li input[type="checkbox"] {
|
||||
<div class="collapse navbar-collapse" id="navbarCollapse">
|
||||
<ul class="navbar-nav navbar-nav-scroll me-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../index.html"> <i class="bi bi-house" role="img">
|
||||
<a class="nav-link active" href="../../index.html" aria-current="page"> <i class="bi bi-house" role="img">
|
||||
</i>
|
||||
<span class="menu-text">Home</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="../../About/index.html" aria-current="page"> <i class="bi bi-file-person" role="img">
|
||||
<a class="nav-link" href="../../About/index.html"> <i class="bi bi-file-person" role="img">
|
||||
</i>
|
||||
<span class="menu-text">About</span></a>
|
||||
</li>
|
||||
@ -307,6 +314,10 @@ ul.task-list li input[type="checkbox"] {
|
||||
<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-article page-navbar">
|
||||
<!-- sidebar -->
|
||||
<nav id="quarto-sidebar" class="sidebar collapse collapse-horizontal quarto-sidebar-collapse-item sidebar-navigation docked overflow-auto">
|
||||
<div class="pt-lg-2 mt-2 text-left sidebar-header">
|
||||
<a href="../../index.html" class="sidebar-logo-link">
|
||||
</a>
|
||||
</div>
|
||||
<div class="sidebar-menu-container">
|
||||
<ul class="list-unstyled mt-1">
|
||||
<li class="sidebar-item sidebar-item-section">
|
||||
@ -350,12 +361,6 @@ ul.task-list li input[type="checkbox"] {
|
||||
<a href="../../Writing/Obsidian-RAG.html" class="sidebar-item-text sidebar-link">
|
||||
<span class="menu-text">RAG für eine Obsidian-Wissensdatenbank: Technische Ansätze</span></a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="../../Obsidian-Articles/Artikelbewertung durch LLM.html" class="sidebar-item-text sidebar-link">
|
||||
<span class="menu-text">Artikelbewertung durch ein Large Language Model (LLM) - Ein Beispiel aus der Praxis</span></a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
@ -696,7 +701,7 @@ ul.task-list li input[type="checkbox"] {
|
||||
a.appendChild(i);
|
||||
window.document.body.appendChild(a);
|
||||
}
|
||||
window.setColorSchemeToggle(window.hasAlternateSentinel())
|
||||
setColorSchemeToggle(hasAlternateSentinel())
|
||||
const icon = "";
|
||||
const anchorJS = new window.AnchorJS();
|
||||
anchorJS.options = {
|
||||
|
103
dist/Coding/Haskell/Code Snippets/Monoid.html
vendored
103
dist/Coding/Haskell/Code Snippets/Monoid.html
vendored
@ -2,7 +2,7 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="generator" content="quarto-1.7.23">
|
||||
<meta name="generator" content="quarto-1.8.17">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||||
|
||||
@ -68,17 +68,19 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<meta name="quarto:offset" content="../../../">
|
||||
<script src="../../../site_libs/quarto-html/quarto.js" type="module"></script>
|
||||
<script src="../../../site_libs/quarto-html/tabsets/tabsets.js" type="module"></script>
|
||||
<script src="../../../site_libs/quarto-html/axe/axe-check.js" type="module"></script>
|
||||
<script src="../../../site_libs/quarto-html/popper.min.js"></script>
|
||||
<script src="../../../site_libs/quarto-html/tippy.umd.min.js"></script>
|
||||
<script src="../../../site_libs/quarto-html/anchor.min.js"></script>
|
||||
<link href="../../../site_libs/quarto-html/tippy.css" rel="stylesheet">
|
||||
<link href="../../../site_libs/quarto-html/quarto-syntax-highlighting-dark-2c84ecb840a13f4c7993f9e5648f0c14.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles">
|
||||
<link href="../../../site_libs/quarto-html/quarto-syntax-highlighting-6cf5824034cebd0380a5b9c74c43f006.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles">
|
||||
<link href="../../../site_libs/quarto-html/quarto-syntax-highlighting-ff1c8a91a872873ab9706226229f9e30.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles">
|
||||
<link href="../../../site_libs/quarto-html/quarto-syntax-highlighting-dark-04b38c9dba5d7c0f1fe2b621b39e7e62.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles">
|
||||
<link href="../../../site_libs/quarto-html/quarto-syntax-highlighting-ff1c8a91a872873ab9706226229f9e30.css" rel="stylesheet" class="quarto-color-scheme-extra" id="quarto-text-highlighting-styles">
|
||||
<script src="../../../site_libs/bootstrap/bootstrap.min.js"></script>
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-ec71cb1e120c0dd41819aca960e74e38.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-dark-716ed94a23403968eaa6fe981e0cbf91.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="dark">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-ec71cb1e120c0dd41819aca960e74e38.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme-extra" id="quarto-bootstrap" data-mode="light">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-9b56b6674ace31b1957ea5f5ef42286f.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-dark-3c8015a3c2181875b3e8a350495bd83c.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="dark">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-9b56b6674ace31b1957ea5f5ef42286f.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme-extra" id="quarto-bootstrap" data-mode="light">
|
||||
<script id="quarto-search-options" type="application/json">{
|
||||
"location": "navbar",
|
||||
"copy-button": false,
|
||||
@ -131,7 +133,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
toggleBodyColorMode(bsSheetEl);
|
||||
}
|
||||
}
|
||||
window.setColorSchemeToggle = (alternate) => {
|
||||
const setColorSchemeToggle = (alternate) => {
|
||||
const toggles = window.document.querySelectorAll('.quarto-color-scheme-toggle');
|
||||
for (let i=0; i < toggles.length; i++) {
|
||||
const toggle = toggles[i];
|
||||
@ -164,7 +166,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
}
|
||||
manageTransitions('#quarto-margin-sidebar .nav-link', true);
|
||||
// Switch the toggles
|
||||
window.setColorSchemeToggle(alternate)
|
||||
setColorSchemeToggle(alternate)
|
||||
// Hack to workaround the fact that safari doesn't
|
||||
// properly recolor the scrollbar when toggling (#1455)
|
||||
if (navigator.userAgent.indexOf('Safari') > 0 && navigator.userAgent.indexOf('Chrome') == -1) {
|
||||
@ -204,7 +206,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
const isFileUrl = () => {
|
||||
return window.location.protocol === 'file:';
|
||||
}
|
||||
window.hasAlternateSentinel = () => {
|
||||
const hasAlternateSentinel = () => {
|
||||
let styleSentinel = getColorSchemeSentinel();
|
||||
if (styleSentinel !== null) {
|
||||
return styleSentinel === "alternate";
|
||||
@ -232,7 +234,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
const baseTheme = document.querySelector('#giscus-base-theme')?.value ?? 'light';
|
||||
const alternateTheme = document.querySelector('#giscus-alt-theme')?.value ?? 'dark';
|
||||
let newTheme = '';
|
||||
if(darkModeDefault) {
|
||||
if(authorPrefersDark) {
|
||||
newTheme = isAlternate ? baseTheme : alternateTheme;
|
||||
} else {
|
||||
newTheme = isAlternate ? alternateTheme : baseTheme;
|
||||
@ -255,17 +257,20 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
changeGiscusTheme();
|
||||
}
|
||||
};
|
||||
const authorPrefersDark = false;
|
||||
const queryPrefersDark = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
const darkModeDefault = queryPrefersDark.matches;
|
||||
document.querySelector('link.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
|
||||
document.querySelector('link#quarto-text-highlighting-styles.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
|
||||
document.querySelector('link#quarto-bootstrap.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
|
||||
let localAlternateSentinel = darkModeDefault ? 'alternate' : 'default';
|
||||
// Dark / light mode switch
|
||||
window.quartoToggleColorScheme = () => {
|
||||
// Read the current dark / light value
|
||||
let toAlternate = !window.hasAlternateSentinel();
|
||||
let toAlternate = !hasAlternateSentinel();
|
||||
toggleColorMode(toAlternate);
|
||||
setStyleSentinel(toAlternate);
|
||||
toggleGiscusIfUsed(toAlternate, darkModeDefault);
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
};
|
||||
queryPrefersDark.addEventListener("change", e => {
|
||||
if(window.localStorage.getItem("quarto-color-scheme") !== null)
|
||||
@ -276,7 +281,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
toggleGiscusIfUsed(alternate, darkModeDefault);
|
||||
});
|
||||
// Switch to dark mode if need be
|
||||
if (window.hasAlternateSentinel()) {
|
||||
if (hasAlternateSentinel()) {
|
||||
toggleColorMode(true);
|
||||
} else {
|
||||
toggleColorMode(false);
|
||||
@ -288,6 +293,8 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<nav class="navbar navbar-expand-lg " data-bs-theme="dark">
|
||||
<div class="navbar-container container-fluid">
|
||||
<div class="navbar-brand-container mx-auto">
|
||||
<a href="../../../index.html" class="navbar-brand navbar-brand-logo">
|
||||
</a>
|
||||
<a class="navbar-brand" href="../../../index.html">
|
||||
<span class="navbar-title">Nicole Dresselhaus</span>
|
||||
</a>
|
||||
@ -299,12 +306,12 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<div class="collapse navbar-collapse" id="navbarCollapse">
|
||||
<ul class="navbar-nav navbar-nav-scroll me-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../../index.html"> <i class="bi bi-house" role="img">
|
||||
<a class="nav-link active" href="../../../index.html" aria-current="page"> <i class="bi bi-house" role="img">
|
||||
</i>
|
||||
<span class="menu-text">Home</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="../../../About/index.html" aria-current="page"> <i class="bi bi-file-person" role="img">
|
||||
<a class="nav-link" href="../../../About/index.html"> <i class="bi bi-file-person" role="img">
|
||||
</i>
|
||||
<span class="menu-text">About</span></a>
|
||||
</li>
|
||||
@ -342,6 +349,10 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-article page-navbar">
|
||||
<!-- sidebar -->
|
||||
<nav id="quarto-sidebar" class="sidebar collapse collapse-horizontal quarto-sidebar-collapse-item sidebar-navigation docked overflow-auto">
|
||||
<div class="pt-lg-2 mt-2 text-left sidebar-header">
|
||||
<a href="../../../index.html" class="sidebar-logo-link">
|
||||
</a>
|
||||
</div>
|
||||
<div class="sidebar-menu-container">
|
||||
<ul class="list-unstyled mt-1">
|
||||
<li class="sidebar-item sidebar-item-section">
|
||||
@ -385,12 +396,6 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<a href="../../../Writing/Obsidian-RAG.html" class="sidebar-item-text sidebar-link">
|
||||
<span class="menu-text">RAG für eine Obsidian-Wissensdatenbank: Technische Ansätze</span></a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="../../../Obsidian-Articles/Artikelbewertung durch LLM.html" class="sidebar-item-text sidebar-link">
|
||||
<span class="menu-text">Artikelbewertung durch ein Large Language Model (LLM) - Ein Beispiel aus der Praxis</span></a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
@ -663,7 +668,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
|
||||
|
||||
<p>Stellen wir uns vor, dass wir eine Funktion schreiben, die einen String bekommt (mehrere Lines mit ACSII-Text) und dieses Wort-für-Wort rückwärts ausgeben soll. Das ist ein einfacher Einzeiler:</p>
|
||||
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> <span class="dt">Main</span> <span class="kw">where</span></span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> <span class="dt">Main</span> <span class="kw">where</span></span>
|
||||
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">System.Environment</span> (getArgs)</span>
|
||||
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Monoid</span> (mconcat)</span>
|
||||
@ -671,30 +676,30 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span>
|
||||
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a> ls <span class="ot"><-</span> <span class="fu">readFile</span> <span class="op">=<<</span> <span class="fu">head</span> <span class="op"><$></span> getArgs</span>
|
||||
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a> <span class="fu">mconcat</span> <span class="op"><$></span> <span class="fu">mapM</span> (<span class="fu">putStrLn</span> <span class="op">.</span> <span class="fu">unwords</span> <span class="op">.</span> <span class="fu">reverse</span> <span class="op">.</span> <span class="fu">words</span>) (<span class="fu">lines</span> ls) <span class="co">--die eigentliche Funktion, ls ist das argument.</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a> <span class="fu">mconcat</span> <span class="op"><$></span> <span class="fu">mapM</span> (<span class="fu">putStrLn</span> <span class="op">.</span> <span class="fu">unwords</span> <span class="op">.</span> <span class="fu">reverse</span> <span class="op">.</span> <span class="fu">words</span>) (<span class="fu">lines</span> ls) <span class="co">--die eigentliche Funktion, ls ist das argument.</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Was passiert hier an Vodoo? Und was machen die ganzen wilden Zeichen da?</p>
|
||||
<p>Gehen wir die Main zeilenweise durch: Wir lesen die Datei, die im ersten Kommandozeilen-Argument gegeben wird. getArgs hat folgende Signatur:</p>
|
||||
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ot">getArgs ::</span> <span class="dt">IO</span> [<span class="dt">String</span>]</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ot">getArgs ::</span> <span class="dt">IO</span> [<span class="dt">String</span>]</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Wir bekommen als eine Liste der Argumente. Wir wollen nur das erste. Also machen wir head getArgs. Allerdings fliegt uns dann ein Fehler. head sieht nämlich so aus:</p>
|
||||
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="fu">head</span><span class="ot"> ::</span> [a] <span class="ot">-></span> a</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="fu">head</span><span class="ot"> ::</span> [a] <span class="ot">-></span> a</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Irgendwie müssen wird as <strong>in</strong> das IO bekommen. Hierzu gibt es fmap. Somit ist</p>
|
||||
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="fu">fmap</span><span class="ot"> head ::</span> <span class="dt">IO</span> [a] <span class="ot">-></span> <span class="dt">IO</span> a</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="fu">fmap</span><span class="ot"> head ::</span> <span class="dt">IO</span> [a] <span class="ot">-></span> <span class="dt">IO</span> a</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Ein inline-Alias (um die Funktion links und das Argument rechts zu schreiben und sich ne Menge Klammern zu sparen) ist <$>. Somit ist schlussendlich der Inhalt der Datei aus dem ersten Argument (lazy) in ls.</p>
|
||||
<p>Eine andere Möglichkeit sich das (in diesem Fall) zu merken, bzw. drauf zu kommen ist, dass [] AUCH ein Funktor (sogar eine Monade) ist. Man könnte das also auch so schreiben:</p>
|
||||
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="fu">head</span><span class="ot"> ::</span> [] a <span class="ot">-></span> a</span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="fu">head</span><span class="ot"> ::</span> [] a <span class="ot">-></span> a</span>
|
||||
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="fu">head</span><span class="ot"> ::</span> <span class="dt">Functor</span> f <span class="ot">=></span> [] (f a) <span class="ot">-></span> f a <span class="co">-- das "a" geschickt ersetzt zur Verdeutlichung</span></span>
|
||||
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="ot">getArgs ::</span> <span class="dt">IO</span> [] <span class="dt">String</span></span>
|
||||
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="fu">fmap</span><span class="ot"> head ::</span> <span class="dt">Functor</span> f <span class="ot">=></span> f [] a <span class="ot">-></span> f a</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="fu">fmap</span><span class="ot"> head ::</span> <span class="dt">Functor</span> f <span class="ot">=></span> f [] a <span class="ot">-></span> f a</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>fmap “packt” die Funktion quasi 1 Umgebung (Funktor, Monade, ..) weiter rein - Sei es nun in Maybe, Either oder irgendwas anderes.</p>
|
||||
<p>Alternatives (ausführliches) Beispiel am Ende.</p>
|
||||
<p>Wenn wir uns die Signatur ansehen, dann haben wir nun</p>
|
||||
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="fu">head</span> <span class="op"><$></span><span class="ot"> getArgs ::</span> <span class="dt">IO</span> <span class="dt">String</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="fu">head</span> <span class="op"><$></span><span class="ot"> getArgs ::</span> <span class="dt">IO</span> <span class="dt">String</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>readFile will aber nun ein String haben. Man kann nun</p>
|
||||
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>f <span class="ot"><-</span> <span class="fu">head</span> <span class="op"><$></span> getArgs</span>
|
||||
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>ls <span class="ot"><-</span> <span class="fu">readFile</span> f</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>f <span class="ot"><-</span> <span class="fu">head</span> <span class="op"><$></span> getArgs</span>
|
||||
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>ls <span class="ot"><-</span> <span class="fu">readFile</span> f</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>kann man auch “inline” mit =<< die Sachen “auspacken”.</p>
|
||||
<p>Die 2. Zeile lesen wir nun einfach “von hinten”, wie man das meistens tun sollte. Hier ist ein</p>
|
||||
<div class="sourceCode" id="cb8"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="fu">lines</span><span class="ot"> ls ::</span> [<span class="dt">String</span>]</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="fu">lines</span><span class="ot"> ls ::</span> [<span class="dt">String</span>]</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>was uns den Inhalt der Datei zeilenweise gibt. Mit jeder Zeile möchten wir nun folgendes machen:</p>
|
||||
<ol type="1">
|
||||
<li>nach Wörtern trennen (words)</li>
|
||||
@ -703,42 +708,42 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<li>diese Zeile ausgeben (putStrLn)</li>
|
||||
</ol>
|
||||
<p>Wenn wir uns die Signatur ansehen:</p>
|
||||
<div class="sourceCode" id="cb9"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>(<span class="fu">putStrLn</span> <span class="op">.</span> <span class="fu">unwords</span> <span class="op">.</span> <span class="fu">reverse</span> <span class="op">.</span> <span class="fu">words</span>)<span class="ot"> ::</span> <span class="dt">String</span> <span class="ot">-></span> <span class="dt">IO</span> ()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb9"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>(<span class="fu">putStrLn</span> <span class="op">.</span> <span class="fu">unwords</span> <span class="op">.</span> <span class="fu">reverse</span> <span class="op">.</span> <span class="fu">words</span>)<span class="ot"> ::</span> <span class="dt">String</span> <span class="ot">-></span> <span class="dt">IO</span> ()</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Das mag im ersten Moment verwirren, daher noch die Signaturen der Einzelfunktionen:</p>
|
||||
<div class="sourceCode" id="cb10"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="fu">words</span><span class="ot"> ::</span> <span class="dt">String</span> <span class="ot">-></span> [<span class="dt">String</span>]</span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb10"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="fu">words</span><span class="ot"> ::</span> <span class="dt">String</span> <span class="ot">-></span> [<span class="dt">String</span>]</span>
|
||||
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="fu">reverse</span><span class="ot"> ::</span> [a] <span class="ot">-></span> [a]</span>
|
||||
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="fu">unwords</span><span class="ot"> ::</span> [<span class="dt">String</span>] <span class="ot">-></span> <span class="dt">String</span></span>
|
||||
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="fu">putStrLn</span><span class="ot"> ::</span> <span class="dt">String</span> <span class="ot">-></span> <span class="dt">IO</span> ()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="fu">putStrLn</span><span class="ot"> ::</span> <span class="dt">String</span> <span class="ot">-></span> <span class="dt">IO</span> ()</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Da wir am Ende in der IO-Monade landen müssen wir das auf unsere Zeilen mit mapM statt map anwenden. Dies sorgt auch dafür, dass die Liste der reihe nach durchgegangen wird. mapM mit unserer Funktion schaut dann so aus:</p>
|
||||
<div class="sourceCode" id="cb11"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="fu">mapM</span> (<span class="fu">putStrLn</span> <span class="op">.</span> <span class="fu">unwords</span> <span class="op">.</span> <span class="fu">reverse</span> <span class="op">.</span> <span class="fu">words</span>)<span class="ot"> ::</span> [<span class="dt">String</span>] <span class="ot">-></span> [<span class="dt">IO</span> ()]</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb11"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="fu">mapM</span> (<span class="fu">putStrLn</span> <span class="op">.</span> <span class="fu">unwords</span> <span class="op">.</span> <span class="fu">reverse</span> <span class="op">.</span> <span class="fu">words</span>)<span class="ot"> ::</span> [<span class="dt">String</span>] <span class="ot">-></span> [<span class="dt">IO</span> ()]</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>eek! Das [IO ()] sieht ekelig aus. Wir haben eine Liste von IO-gar nichts. Das können wir eigentlich entsorgen. Da wir innerhalb der main-Funktion in einer IO-Monade sind, wollen wir IO () anstatt [IO ()] zurück haben.</p>
|
||||
<p>Wenn wir uns jetzt erinnern, dass [] auch nur eine Monade ist und dass jede Monade ein Monoid ist, dann ist die Lösung einfach. Monoide haben eine “append”-funktion (mappend oder (<>) genannt). Wenn wir “nichts” an “nichts” anhängen, dann erhalten wir …. <em>Trommelwirbel</em> “nichts”! Wir müssen die [IO ()]-Liste also “nur noch” mit mappend falten. Hierzu gibt es schon eine vorgefertigte Funktion:</p>
|
||||
<div class="sourceCode" id="cb12"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="fu">mconcat</span><span class="ot"> ::</span> [a] <span class="ot">-></span> a</span>
|
||||
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="fu">mconcat</span> <span class="ot">=</span> <span class="fu">foldr</span> <span class="fu">mappend</span> <span class="fu">mempty</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb12"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="fu">mconcat</span><span class="ot"> ::</span> [a] <span class="ot">-></span> a</span>
|
||||
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="fu">mconcat</span> <span class="ot">=</span> <span class="fu">foldr</span> <span class="fu">mappend</span> <span class="fu">mempty</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Was genau die gewünschte Faltung macht. Wir müssen nun wieder fmap nehmen, da wir die Liste selbst falten wollen - und nicht map, welches auf den IO () innerhalb der Liste arbeiten würde. Durch die Faltung fällt die Liste nun auf IO () zusammen.</p>
|
||||
<p>Viel Voodoo in wenig Code, aber wenn man sich dran gewöhnt hat, sind Monaden in Monaden auch nicht schlimm. Man muss sich immer nur richtig “rein” fmap’en.</p>
|
||||
<hr>
|
||||
<p>Kleinen Tipp gab es noch: mapM_ macht genau das, was oben mit mconcat erreicht werden sollte. Somit kann man auch</p>
|
||||
<div class="sourceCode" id="cb13"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="fu">mapM_</span> (<span class="fu">putStrLn</span> <span class="op">.</span> <span class="fu">unwords</span> <span class="op">.</span> <span class="fu">reverse</span> <span class="op">.</span> <span class="fu">words</span>) (<span class="fu">lines</span> ls)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb13"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="fu">mapM_</span> (<span class="fu">putStrLn</span> <span class="op">.</span> <span class="fu">unwords</span> <span class="op">.</span> <span class="fu">reverse</span> <span class="op">.</span> <span class="fu">words</span>) (<span class="fu">lines</span> ls)</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>schreiben. Ich hab es aber mal wegen der klarheit oben so gelassen.</p>
|
||||
<section id="alternatives-fmap-beispiel" class="level2">
|
||||
<h2 class="anchored" data-anchor-id="alternatives-fmap-beispiel">Alternatives fmap-Beispiel</h2>
|
||||
<p>Nehmen wir als alternatives Beispiel mal an:</p>
|
||||
<div class="sourceCode" id="cb14"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="ot">a ::</span> <span class="dt">IO</span> <span class="dt">Maybe</span> <span class="dt">State</span> t</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb14"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="ot">a ::</span> <span class="dt">IO</span> <span class="dt">Maybe</span> <span class="dt">State</span> t</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Um Funktionen vom Typ</p>
|
||||
<div class="sourceCode" id="cb15"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="ot">f ::</span> <span class="dt">IO</span> a <span class="ot">-></span> <span class="dt">IO</span> a</span>
|
||||
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>f a <span class="co">-- valide</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb15"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="ot">f ::</span> <span class="dt">IO</span> a <span class="ot">-></span> <span class="dt">IO</span> a</span>
|
||||
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>f a <span class="co">-- valide</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>zu nehmen, brauchen wir nichts machen. Bei</p>
|
||||
<div class="sourceCode" id="cb16"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="ot">f' ::</span> <span class="dt">Maybe</span> a <span class="ot">-></span> <span class="dt">Maybe</span> a</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb16"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="ot">f' ::</span> <span class="dt">Maybe</span> a <span class="ot">-></span> <span class="dt">Maybe</span> a</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>brauchen wir 1 fmap, also ein</p>
|
||||
<div class="sourceCode" id="cb17"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a>f' a <span class="co">-- error</span></span>
|
||||
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>f' <span class="op"><$></span> a</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb17"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a>f' a <span class="co">-- error</span></span>
|
||||
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>f' <span class="op"><$></span> a</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>um eine Funktion</p>
|
||||
<div class="sourceCode" id="cb18"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="ot">f'' ::</span> <span class="dt">State</span> t <span class="ot">-></span> <span class="dt">State</span> t</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb18"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="ot">f'' ::</span> <span class="dt">State</span> t <span class="ot">-></span> <span class="dt">State</span> t</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>zu benutzen folglich:</p>
|
||||
<div class="sourceCode" id="cb19"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a>f'' a <span class="co">-- error</span></span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb19"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a>f'' a <span class="co">-- error</span></span>
|
||||
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>f'' <span class="op"><$></span> a <span class="co">-- error</span></span>
|
||||
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a><span class="fu">fmap</span> f'' <span class="op"><$></span> a</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a><span class="fu">fmap</span> f'' <span class="op"><$></span> a</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
|
||||
|
||||
</section>
|
||||
@ -758,7 +763,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
a.appendChild(i);
|
||||
window.document.body.appendChild(a);
|
||||
}
|
||||
window.setColorSchemeToggle(window.hasAlternateSentinel())
|
||||
setColorSchemeToggle(hasAlternateSentinel())
|
||||
const icon = "";
|
||||
const anchorJS = new window.AnchorJS();
|
||||
anchorJS.options = {
|
||||
|
91
dist/Coding/Haskell/Code Snippets/Morphisms.html
vendored
91
dist/Coding/Haskell/Code Snippets/Morphisms.html
vendored
@ -2,7 +2,7 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="generator" content="quarto-1.7.23">
|
||||
<meta name="generator" content="quarto-1.8.17">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||||
|
||||
@ -68,17 +68,19 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<meta name="quarto:offset" content="../../../">
|
||||
<script src="../../../site_libs/quarto-html/quarto.js" type="module"></script>
|
||||
<script src="../../../site_libs/quarto-html/tabsets/tabsets.js" type="module"></script>
|
||||
<script src="../../../site_libs/quarto-html/axe/axe-check.js" type="module"></script>
|
||||
<script src="../../../site_libs/quarto-html/popper.min.js"></script>
|
||||
<script src="../../../site_libs/quarto-html/tippy.umd.min.js"></script>
|
||||
<script src="../../../site_libs/quarto-html/anchor.min.js"></script>
|
||||
<link href="../../../site_libs/quarto-html/tippy.css" rel="stylesheet">
|
||||
<link href="../../../site_libs/quarto-html/quarto-syntax-highlighting-dark-2c84ecb840a13f4c7993f9e5648f0c14.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles">
|
||||
<link href="../../../site_libs/quarto-html/quarto-syntax-highlighting-6cf5824034cebd0380a5b9c74c43f006.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles">
|
||||
<link href="../../../site_libs/quarto-html/quarto-syntax-highlighting-ff1c8a91a872873ab9706226229f9e30.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles">
|
||||
<link href="../../../site_libs/quarto-html/quarto-syntax-highlighting-dark-04b38c9dba5d7c0f1fe2b621b39e7e62.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles">
|
||||
<link href="../../../site_libs/quarto-html/quarto-syntax-highlighting-ff1c8a91a872873ab9706226229f9e30.css" rel="stylesheet" class="quarto-color-scheme-extra" id="quarto-text-highlighting-styles">
|
||||
<script src="../../../site_libs/bootstrap/bootstrap.min.js"></script>
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-ec71cb1e120c0dd41819aca960e74e38.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-dark-716ed94a23403968eaa6fe981e0cbf91.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="dark">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-ec71cb1e120c0dd41819aca960e74e38.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme-extra" id="quarto-bootstrap" data-mode="light">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-9b56b6674ace31b1957ea5f5ef42286f.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-dark-3c8015a3c2181875b3e8a350495bd83c.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="dark">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-9b56b6674ace31b1957ea5f5ef42286f.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme-extra" id="quarto-bootstrap" data-mode="light">
|
||||
<script id="quarto-search-options" type="application/json">{
|
||||
"location": "navbar",
|
||||
"copy-button": false,
|
||||
@ -133,7 +135,7 @@ Knowing that this might sound daunting to many dabbling Haskellers (like I am),
|
||||
toggleBodyColorMode(bsSheetEl);
|
||||
}
|
||||
}
|
||||
window.setColorSchemeToggle = (alternate) => {
|
||||
const setColorSchemeToggle = (alternate) => {
|
||||
const toggles = window.document.querySelectorAll('.quarto-color-scheme-toggle');
|
||||
for (let i=0; i < toggles.length; i++) {
|
||||
const toggle = toggles[i];
|
||||
@ -166,7 +168,7 @@ Knowing that this might sound daunting to many dabbling Haskellers (like I am),
|
||||
}
|
||||
manageTransitions('#quarto-margin-sidebar .nav-link', true);
|
||||
// Switch the toggles
|
||||
window.setColorSchemeToggle(alternate)
|
||||
setColorSchemeToggle(alternate)
|
||||
// Hack to workaround the fact that safari doesn't
|
||||
// properly recolor the scrollbar when toggling (#1455)
|
||||
if (navigator.userAgent.indexOf('Safari') > 0 && navigator.userAgent.indexOf('Chrome') == -1) {
|
||||
@ -206,7 +208,7 @@ Knowing that this might sound daunting to many dabbling Haskellers (like I am),
|
||||
const isFileUrl = () => {
|
||||
return window.location.protocol === 'file:';
|
||||
}
|
||||
window.hasAlternateSentinel = () => {
|
||||
const hasAlternateSentinel = () => {
|
||||
let styleSentinel = getColorSchemeSentinel();
|
||||
if (styleSentinel !== null) {
|
||||
return styleSentinel === "alternate";
|
||||
@ -234,7 +236,7 @@ Knowing that this might sound daunting to many dabbling Haskellers (like I am),
|
||||
const baseTheme = document.querySelector('#giscus-base-theme')?.value ?? 'light';
|
||||
const alternateTheme = document.querySelector('#giscus-alt-theme')?.value ?? 'dark';
|
||||
let newTheme = '';
|
||||
if(darkModeDefault) {
|
||||
if(authorPrefersDark) {
|
||||
newTheme = isAlternate ? baseTheme : alternateTheme;
|
||||
} else {
|
||||
newTheme = isAlternate ? alternateTheme : baseTheme;
|
||||
@ -257,17 +259,20 @@ Knowing that this might sound daunting to many dabbling Haskellers (like I am),
|
||||
changeGiscusTheme();
|
||||
}
|
||||
};
|
||||
const authorPrefersDark = false;
|
||||
const queryPrefersDark = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
const darkModeDefault = queryPrefersDark.matches;
|
||||
document.querySelector('link.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
|
||||
document.querySelector('link#quarto-text-highlighting-styles.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
|
||||
document.querySelector('link#quarto-bootstrap.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
|
||||
let localAlternateSentinel = darkModeDefault ? 'alternate' : 'default';
|
||||
// Dark / light mode switch
|
||||
window.quartoToggleColorScheme = () => {
|
||||
// Read the current dark / light value
|
||||
let toAlternate = !window.hasAlternateSentinel();
|
||||
let toAlternate = !hasAlternateSentinel();
|
||||
toggleColorMode(toAlternate);
|
||||
setStyleSentinel(toAlternate);
|
||||
toggleGiscusIfUsed(toAlternate, darkModeDefault);
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
};
|
||||
queryPrefersDark.addEventListener("change", e => {
|
||||
if(window.localStorage.getItem("quarto-color-scheme") !== null)
|
||||
@ -278,7 +283,7 @@ Knowing that this might sound daunting to many dabbling Haskellers (like I am),
|
||||
toggleGiscusIfUsed(alternate, darkModeDefault);
|
||||
});
|
||||
// Switch to dark mode if need be
|
||||
if (window.hasAlternateSentinel()) {
|
||||
if (hasAlternateSentinel()) {
|
||||
toggleColorMode(true);
|
||||
} else {
|
||||
toggleColorMode(false);
|
||||
@ -290,6 +295,8 @@ Knowing that this might sound daunting to many dabbling Haskellers (like I am),
|
||||
<nav class="navbar navbar-expand-lg " data-bs-theme="dark">
|
||||
<div class="navbar-container container-fluid">
|
||||
<div class="navbar-brand-container mx-auto">
|
||||
<a href="../../../index.html" class="navbar-brand navbar-brand-logo">
|
||||
</a>
|
||||
<a class="navbar-brand" href="../../../index.html">
|
||||
<span class="navbar-title">Nicole Dresselhaus</span>
|
||||
</a>
|
||||
@ -301,12 +308,12 @@ Knowing that this might sound daunting to many dabbling Haskellers (like I am),
|
||||
<div class="collapse navbar-collapse" id="navbarCollapse">
|
||||
<ul class="navbar-nav navbar-nav-scroll me-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../../index.html"> <i class="bi bi-house" role="img">
|
||||
<a class="nav-link active" href="../../../index.html" aria-current="page"> <i class="bi bi-house" role="img">
|
||||
</i>
|
||||
<span class="menu-text">Home</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="../../../About/index.html" aria-current="page"> <i class="bi bi-file-person" role="img">
|
||||
<a class="nav-link" href="../../../About/index.html"> <i class="bi bi-file-person" role="img">
|
||||
</i>
|
||||
<span class="menu-text">About</span></a>
|
||||
</li>
|
||||
@ -344,6 +351,10 @@ Knowing that this might sound daunting to many dabbling Haskellers (like I am),
|
||||
<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-article page-navbar">
|
||||
<!-- sidebar -->
|
||||
<nav id="quarto-sidebar" class="sidebar collapse collapse-horizontal quarto-sidebar-collapse-item sidebar-navigation docked overflow-auto">
|
||||
<div class="pt-lg-2 mt-2 text-left sidebar-header">
|
||||
<a href="../../../index.html" class="sidebar-logo-link">
|
||||
</a>
|
||||
</div>
|
||||
<div class="sidebar-menu-container">
|
||||
<ul class="list-unstyled mt-1">
|
||||
<li class="sidebar-item sidebar-item-section">
|
||||
@ -387,12 +398,6 @@ Knowing that this might sound daunting to many dabbling Haskellers (like I am),
|
||||
<a href="../../../Writing/Obsidian-RAG.html" class="sidebar-item-text sidebar-link">
|
||||
<span class="menu-text">RAG für eine Obsidian-Wissensdatenbank: Technische Ansätze</span></a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="../../../Obsidian-Articles/Artikelbewertung durch LLM.html" class="sidebar-item-text sidebar-link">
|
||||
<span class="menu-text">Artikelbewertung durch ein Large Language Model (LLM) - Ein Beispiel aus der Praxis</span></a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
@ -679,45 +684,45 @@ Note
|
||||
<p>For those who need a refresher: MergeSort works by creating a balanced binary tree from the input list and directly collapsing it back into itself while treating the children as sorted lists and merging these with an O(n) algorithm.</p>
|
||||
<hr>
|
||||
<p>First the usual prelude:</p>
|
||||
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE DeriveFunctor #-}</span></span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE DeriveFunctor #-}</span></span>
|
||||
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE TypeFamilies #-}</span></span>
|
||||
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Functor.Foldable</span></span>
|
||||
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.List</span> (splitAt, unfoldr)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.List</span> (splitAt, unfoldr)</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<hr>
|
||||
<p>We will use a binary tree like this. Note that there is no explicit recursion used, but <code>NodeF</code> has two <em>holes</em>. These will eventually filled later.</p>
|
||||
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">TreeF</span> c f <span class="ot">=</span> <span class="dt">EmptyF</span> <span class="op">|</span> <span class="dt">LeafF</span> c <span class="op">|</span> <span class="dt">NodeF</span> f f</span>
|
||||
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">deriving</span> (<span class="dt">Eq</span>, <span class="dt">Show</span>, <span class="dt">Functor</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">TreeF</span> c f <span class="ot">=</span> <span class="dt">EmptyF</span> <span class="op">|</span> <span class="dt">LeafF</span> c <span class="op">|</span> <span class="dt">NodeF</span> f f</span>
|
||||
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">deriving</span> (<span class="dt">Eq</span>, <span class="dt">Show</span>, <span class="dt">Functor</span>)</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<hr>
|
||||
<p>Aside: We could use this as a <em>normal</em> binary tree by wrapping it in <code>Fix</code>: <code>type Tree a = Fix (TreeF a)</code> But this would require us to write our tree like <code>Fix (NodeF (Fix (LeafF 'l')) (Fix (LeafF 'r')))</code> which would get tedious fast. Luckily Edward build a much better way to do this into <em>recursion-schemes</em>. I will touch on this later.</p>
|
||||
<hr>
|
||||
<p>Without further ado we start to write a Coalgebra, which in my book is just a scary name for “function that is used to construct datastructures”.</p>
|
||||
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ot">unflatten ::</span> [a] <span class="ot">-></span> <span class="dt">TreeF</span> a [a]</span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ot">unflatten ::</span> [a] <span class="ot">-></span> <span class="dt">TreeF</span> a [a]</span>
|
||||
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>unflatten ( []) <span class="ot">=</span> <span class="dt">EmptyF</span></span>
|
||||
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>unflatten (x<span class="op">:</span>[]) <span class="ot">=</span> <span class="dt">LeafF</span> x</span>
|
||||
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>unflatten ( xs) <span class="ot">=</span> <span class="dt">NodeF</span> l r <span class="kw">where</span> (l,r) <span class="ot">=</span> <span class="fu">splitAt</span> (<span class="fu">length</span> xs <span class="ot">`div`</span> <span class="dv">2</span>) xs</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>unflatten ( xs) <span class="ot">=</span> <span class="dt">NodeF</span> l r <span class="kw">where</span> (l,r) <span class="ot">=</span> <span class="fu">splitAt</span> (<span class="fu">length</span> xs <span class="ot">`div`</span> <span class="dv">2</span>) xs</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>From the type signature it’s immediately obvious, that we take a list of ’a’s and use it to create a part of our tree.</p>
|
||||
<p>The nice thing is that due to the fact that we haven’t commited to a type in our tree nodes we can just put lists in there.</p>
|
||||
<hr>
|
||||
<p>Aside: At this point we could use this Coalgebra to construct (unsorted) binary trees from lists:</p>
|
||||
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>example1 <span class="ot">=</span> ana unflatten [<span class="dv">1</span>,<span class="dv">3</span>] <span class="op">==</span> <span class="dt">Fix</span> (<span class="dt">NodeF</span> (<span class="dt">Fix</span> (<span class="dt">LeafF</span> <span class="dv">1</span>)) (<span class="dt">Fix</span> (<span class="dt">LeafF</span> <span class="dv">3</span>)))</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>example1 <span class="ot">=</span> ana unflatten [<span class="dv">1</span>,<span class="dv">3</span>] <span class="op">==</span> <span class="dt">Fix</span> (<span class="dt">NodeF</span> (<span class="dt">Fix</span> (<span class="dt">LeafF</span> <span class="dv">1</span>)) (<span class="dt">Fix</span> (<span class="dt">LeafF</span> <span class="dv">3</span>)))</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<hr>
|
||||
<p>On to our sorting, tree-collapsing Algebra. Which again is just a creepy word for “function that is used to deconstruct datastructures”.</p>
|
||||
<p>The function <code>mergeList</code> is defined below and just merges two sorted lists into one sorted list in O(n), I would probably take this from the <code>ordlist</code> package if I were to implement this <em>for real</em>.</p>
|
||||
<p>Again we see that we can just construct our sorted output list from a <code>TreeF</code> that apparently contains just lists.</p>
|
||||
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ot">flatten ::</span> <span class="dt">Ord</span> a <span class="ot">=></span> <span class="dt">TreeF</span> a [a] <span class="ot">-></span> [a]</span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ot">flatten ::</span> <span class="dt">Ord</span> a <span class="ot">=></span> <span class="dt">TreeF</span> a [a] <span class="ot">-></span> [a]</span>
|
||||
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>flatten <span class="dt">EmptyF</span> <span class="ot">=</span> []</span>
|
||||
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>flatten (<span class="dt">LeafF</span> c) <span class="ot">=</span> [c]</span>
|
||||
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>flatten (<span class="dt">NodeF</span> l r) <span class="ot">=</span> mergeLists l r</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>flatten (<span class="dt">NodeF</span> l r) <span class="ot">=</span> mergeLists l r</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<hr>
|
||||
<p>Aside: We could use a Coalgebra to deconstruct trees:</p>
|
||||
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>example2 <span class="ot">=</span> cata flatten (<span class="dt">Fix</span> (<span class="dt">NodeF</span> (<span class="dt">Fix</span> (<span class="dt">LeafF</span> <span class="dv">3</span>)) (<span class="dt">Fix</span> (<span class="dt">LeafF</span> <span class="dv">1</span>)))) <span class="op">==</span> [<span class="dv">1</span>,<span class="dv">3</span>]</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>example2 <span class="ot">=</span> cata flatten (<span class="dt">Fix</span> (<span class="dt">NodeF</span> (<span class="dt">Fix</span> (<span class="dt">LeafF</span> <span class="dv">3</span>)) (<span class="dt">Fix</span> (<span class="dt">LeafF</span> <span class="dv">1</span>)))) <span class="op">==</span> [<span class="dv">1</span>,<span class="dv">3</span>]</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<hr>
|
||||
<p>Now we just combine the Coalgebra and the Algebra with one from the functions from Edwards <code>recursion-schemes</code> library:</p>
|
||||
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="ot">mergeSort ::</span> <span class="dt">Ord</span> a <span class="ot">=></span> [a] <span class="ot">-></span> [a]</span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="ot">mergeSort ::</span> <span class="dt">Ord</span> a <span class="ot">=></span> [a] <span class="ot">-></span> [a]</span>
|
||||
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>mergeSort <span class="ot">=</span> hylo flatten unflatten</span>
|
||||
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>example3 <span class="ot">=</span> mergeSort [<span class="dv">5</span>,<span class="dv">2</span>,<span class="dv">7</span>,<span class="dv">9</span>,<span class="dv">1</span>,<span class="dv">4</span>] <span class="op">==</span> [<span class="dv">1</span>,<span class="dv">2</span>,<span class="dv">4</span>,<span class="dv">5</span>,<span class="dv">7</span>,<span class="dv">9</span>]</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>example3 <span class="ot">=</span> mergeSort [<span class="dv">5</span>,<span class="dv">2</span>,<span class="dv">7</span>,<span class="dv">9</span>,<span class="dv">1</span>,<span class="dv">4</span>] <span class="op">==</span> [<span class="dv">1</span>,<span class="dv">2</span>,<span class="dv">4</span>,<span class="dv">5</span>,<span class="dv">7</span>,<span class="dv">9</span>]</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<hr>
|
||||
<p>What have we gained?</p>
|
||||
<p>We have implemented a MergeSort variant in 9 lines of code, not counting the <code>mergeLists</code> function below. Not bad, but <a href="http://en.literateprograms.org/Merge_sort_(Haskell)">this implementation</a> is not much longer.</p>
|
||||
@ -726,7 +731,7 @@ Note
|
||||
<hr>
|
||||
<p>At this point I wasn’t sure if this was useful or remotely applicable. Telling someone “I spend a whole weekend learning about Hylomorphism” isn’t something the cool developer kids do.</p>
|
||||
<p>It appeared to me that maybe I should have a look at the Core to see what the compiler finally comes up with (edited for brevity):</p>
|
||||
<div class="sourceCode" id="cb8"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ot"> mergeSort ::</span> [<span class="dt">Integer</span>] <span class="ot">-></span> [<span class="dt">Integer</span>]</span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ot"> mergeSort ::</span> [<span class="dt">Integer</span>] <span class="ot">-></span> [<span class="dt">Integer</span>]</span>
|
||||
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a> mergeSort <span class="ot">=</span></span>
|
||||
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a> \ (<span class="ot">x ::</span> [<span class="dt">Integer</span>]) <span class="ot">-></span></span>
|
||||
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">case</span> x <span class="kw">of</span> wild {</span>
|
||||
@ -753,17 +758,17 @@ Note
|
||||
<span id="cb8-25"><a href="#cb8-25" aria-hidden="true" tabindex="-1"></a> <span class="kw">case</span> p <span class="kw">of</span> _ { (ds1, y) <span class="ot">-></span> mergeSort y }))</span>
|
||||
<span id="cb8-26"><a href="#cb8-26" aria-hidden="true" tabindex="-1"></a> }</span>
|
||||
<span id="cb8-27"><a href="#cb8-27" aria-hidden="true" tabindex="-1"></a> }</span>
|
||||
<span id="cb8-28"><a href="#cb8-28" aria-hidden="true" tabindex="-1"></a> end <span class="dt">Rec</span> }</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb8-28"><a href="#cb8-28" aria-hidden="true" tabindex="-1"></a> end <span class="dt">Rec</span> }</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>While I am not really competent in reading Core and this is actually the first time I bothered to try, it is immediately obvious that there is no trace of any intermediate tree structure.</p>
|
||||
<p>This is when it struck me. I was dazzled and amazed. And am still. Although we are writing our algorithm as if we are working on a real tree structure the library and the compiler are able to just remove the whole intermediate step.</p>
|
||||
<hr>
|
||||
<p>Aftermath:</p>
|
||||
<p>In the beginning I promised a way to work on non-functor data structures. Actually that was how I began to work with the <code>recursion-schemes</code> library.</p>
|
||||
<p>We are able to create a ‘normal’ version of our tree from above:</p>
|
||||
<div class="sourceCode" id="cb9"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Tree</span> c <span class="ot">=</span> <span class="dt">Empty</span> <span class="op">|</span> <span class="dt">Leaf</span> c <span class="op">|</span> <span class="dt">Node</span> (<span class="dt">Tree</span> c) (<span class="dt">Tree</span> c)</span>
|
||||
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">deriving</span> (<span class="dt">Eq</span>, <span class="dt">Show</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb9"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Tree</span> c <span class="ot">=</span> <span class="dt">Empty</span> <span class="op">|</span> <span class="dt">Leaf</span> c <span class="op">|</span> <span class="dt">Node</span> (<span class="dt">Tree</span> c) (<span class="dt">Tree</span> c)</span>
|
||||
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">deriving</span> (<span class="dt">Eq</span>, <span class="dt">Show</span>)</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>But we can not use this directly with our (Co-)Algebras. Luckily Edward build a little bit of type magic into the library:</p>
|
||||
<div class="sourceCode" id="cb10"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="kw">instance</span> <span class="dt">Base</span> (<span class="dt">Tree</span> c) <span class="ot">=</span> (<span class="dt">TreeF</span> c)</span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb10"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="kw">instance</span> <span class="dt">Base</span> (<span class="dt">Tree</span> c) <span class="ot">=</span> (<span class="dt">TreeF</span> c)</span>
|
||||
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Unfoldable</span> (<span class="dt">Tree</span> c) <span class="kw">where</span></span>
|
||||
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a> embed <span class="dt">EmptyF</span> <span class="ot">=</span> <span class="dt">Empty</span></span>
|
||||
@ -773,10 +778,10 @@ Note
|
||||
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Foldable</span> (<span class="dt">Tree</span> c) <span class="kw">where</span></span>
|
||||
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a> project <span class="dt">Empty</span> <span class="ot">=</span> <span class="dt">EmptyF</span></span>
|
||||
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a> project (<span class="dt">Leaf</span> c) <span class="ot">=</span> <span class="dt">LeafF</span> c</span>
|
||||
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a> project (<span class="dt">Node</span> l r) <span class="ot">=</span> <span class="dt">NodeF</span> l r</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a> project (<span class="dt">Node</span> l r) <span class="ot">=</span> <span class="dt">NodeF</span> l r</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Without going into detail by doing this we establish a relationship between <code>Tree</code> and <code>TreeF</code> and teach the compiler how to translate between these types.</p>
|
||||
<p>Now we can use our Alebra on our non functor type:</p>
|
||||
<div class="sourceCode" id="cb11"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>example4 <span class="ot">=</span> cata flatten (<span class="dt">Node</span> (<span class="dt">Leaf</span> <span class="ch">'l'</span>) (<span class="dt">Leaf</span> <span class="ch">'r'</span>)) <span class="op">==</span> <span class="st">"lr"</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb11"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>example4 <span class="ot">=</span> cata flatten (<span class="dt">Node</span> (<span class="dt">Leaf</span> <span class="ch">'l'</span>) (<span class="dt">Leaf</span> <span class="ch">'r'</span>)) <span class="op">==</span> <span class="st">"lr"</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>The great thing about this is that, looking at the Core output again, there is no traces of the <code>TreeF</code> structure to be found. As far as I can tell, the algorithm is working directly on our <code>Tree</code> type.</p>
|
||||
<hr>
|
||||
<p>Literature:</p>
|
||||
@ -788,13 +793,13 @@ Note
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Appendix:</p>
|
||||
<div class="sourceCode" id="cb12"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="ot">mergeLists ::</span> <span class="dt">Ord</span> a <span class="ot">=></span> [a] <span class="ot">-></span> [a] <span class="ot">-></span> [a]</span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb12"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="ot">mergeLists ::</span> <span class="dt">Ord</span> a <span class="ot">=></span> [a] <span class="ot">-></span> [a] <span class="ot">-></span> [a]</span>
|
||||
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>mergeLists <span class="ot">=</span> <span class="fu">curry</span> <span class="op">$</span> unfoldr c <span class="kw">where</span></span>
|
||||
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a> c ([], []) <span class="ot">=</span> <span class="dt">Nothing</span></span>
|
||||
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a> c ([], y<span class="op">:</span>ys) <span class="ot">=</span> <span class="dt">Just</span> (y, ([], ys))</span>
|
||||
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a> c (x<span class="op">:</span>xs, []) <span class="ot">=</span> <span class="dt">Just</span> (x, (xs, []))</span>
|
||||
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a> c (x<span class="op">:</span>xs, y<span class="op">:</span>ys) <span class="op">|</span> x <span class="op"><=</span> y <span class="ot">=</span> <span class="dt">Just</span> (x, (xs, y<span class="op">:</span>ys))</span>
|
||||
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> x <span class="op">></span> y <span class="ot">=</span> <span class="dt">Just</span> (y, (x<span class="op">:</span>xs, ys))</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> x <span class="op">></span> y <span class="ot">=</span> <span class="dt">Just</span> (y, (x<span class="op">:</span>xs, ys))</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
|
||||
|
||||
|
||||
@ -813,7 +818,7 @@ Note
|
||||
a.appendChild(i);
|
||||
window.document.body.appendChild(a);
|
||||
}
|
||||
window.setColorSchemeToggle(window.hasAlternateSentinel())
|
||||
setColorSchemeToggle(hasAlternateSentinel())
|
||||
const icon = "";
|
||||
const anchorJS = new window.AnchorJS();
|
||||
anchorJS.options = {
|
||||
|
49
dist/Coding/Haskell/FFPiH.html
vendored
49
dist/Coding/Haskell/FFPiH.html
vendored
@ -2,7 +2,7 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="generator" content="quarto-1.7.23">
|
||||
<meta name="generator" content="quarto-1.8.17">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||||
|
||||
@ -33,17 +33,19 @@ ul.task-list li input[type="checkbox"] {
|
||||
<meta name="quarto:offset" content="../../">
|
||||
<script src="../../site_libs/quarto-html/quarto.js" type="module"></script>
|
||||
<script src="../../site_libs/quarto-html/tabsets/tabsets.js" type="module"></script>
|
||||
<script src="../../site_libs/quarto-html/axe/axe-check.js" type="module"></script>
|
||||
<script src="../../site_libs/quarto-html/popper.min.js"></script>
|
||||
<script src="../../site_libs/quarto-html/tippy.umd.min.js"></script>
|
||||
<script src="../../site_libs/quarto-html/anchor.min.js"></script>
|
||||
<link href="../../site_libs/quarto-html/tippy.css" rel="stylesheet">
|
||||
<link href="../../site_libs/quarto-html/quarto-syntax-highlighting-dark-2c84ecb840a13f4c7993f9e5648f0c14.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles">
|
||||
<link href="../../site_libs/quarto-html/quarto-syntax-highlighting-6cf5824034cebd0380a5b9c74c43f006.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles">
|
||||
<link href="../../site_libs/quarto-html/quarto-syntax-highlighting-ff1c8a91a872873ab9706226229f9e30.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles">
|
||||
<link href="../../site_libs/quarto-html/quarto-syntax-highlighting-dark-04b38c9dba5d7c0f1fe2b621b39e7e62.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles">
|
||||
<link href="../../site_libs/quarto-html/quarto-syntax-highlighting-ff1c8a91a872873ab9706226229f9e30.css" rel="stylesheet" class="quarto-color-scheme-extra" id="quarto-text-highlighting-styles">
|
||||
<script src="../../site_libs/bootstrap/bootstrap.min.js"></script>
|
||||
<link href="../../site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
|
||||
<link href="../../site_libs/bootstrap/bootstrap-ec71cb1e120c0dd41819aca960e74e38.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light">
|
||||
<link href="../../site_libs/bootstrap/bootstrap-dark-716ed94a23403968eaa6fe981e0cbf91.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="dark">
|
||||
<link href="../../site_libs/bootstrap/bootstrap-ec71cb1e120c0dd41819aca960e74e38.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme-extra" id="quarto-bootstrap" data-mode="light">
|
||||
<link href="../../site_libs/bootstrap/bootstrap-9b56b6674ace31b1957ea5f5ef42286f.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light">
|
||||
<link href="../../site_libs/bootstrap/bootstrap-dark-3c8015a3c2181875b3e8a350495bd83c.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="dark">
|
||||
<link href="../../site_libs/bootstrap/bootstrap-9b56b6674ace31b1957ea5f5ef42286f.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme-extra" id="quarto-bootstrap" data-mode="light">
|
||||
<script id="quarto-search-options" type="application/json">{
|
||||
"location": "navbar",
|
||||
"copy-button": false,
|
||||
@ -96,7 +98,7 @@ ul.task-list li input[type="checkbox"] {
|
||||
toggleBodyColorMode(bsSheetEl);
|
||||
}
|
||||
}
|
||||
window.setColorSchemeToggle = (alternate) => {
|
||||
const setColorSchemeToggle = (alternate) => {
|
||||
const toggles = window.document.querySelectorAll('.quarto-color-scheme-toggle');
|
||||
for (let i=0; i < toggles.length; i++) {
|
||||
const toggle = toggles[i];
|
||||
@ -129,7 +131,7 @@ ul.task-list li input[type="checkbox"] {
|
||||
}
|
||||
manageTransitions('#quarto-margin-sidebar .nav-link', true);
|
||||
// Switch the toggles
|
||||
window.setColorSchemeToggle(alternate)
|
||||
setColorSchemeToggle(alternate)
|
||||
// Hack to workaround the fact that safari doesn't
|
||||
// properly recolor the scrollbar when toggling (#1455)
|
||||
if (navigator.userAgent.indexOf('Safari') > 0 && navigator.userAgent.indexOf('Chrome') == -1) {
|
||||
@ -169,7 +171,7 @@ ul.task-list li input[type="checkbox"] {
|
||||
const isFileUrl = () => {
|
||||
return window.location.protocol === 'file:';
|
||||
}
|
||||
window.hasAlternateSentinel = () => {
|
||||
const hasAlternateSentinel = () => {
|
||||
let styleSentinel = getColorSchemeSentinel();
|
||||
if (styleSentinel !== null) {
|
||||
return styleSentinel === "alternate";
|
||||
@ -197,7 +199,7 @@ ul.task-list li input[type="checkbox"] {
|
||||
const baseTheme = document.querySelector('#giscus-base-theme')?.value ?? 'light';
|
||||
const alternateTheme = document.querySelector('#giscus-alt-theme')?.value ?? 'dark';
|
||||
let newTheme = '';
|
||||
if(darkModeDefault) {
|
||||
if(authorPrefersDark) {
|
||||
newTheme = isAlternate ? baseTheme : alternateTheme;
|
||||
} else {
|
||||
newTheme = isAlternate ? alternateTheme : baseTheme;
|
||||
@ -220,17 +222,20 @@ ul.task-list li input[type="checkbox"] {
|
||||
changeGiscusTheme();
|
||||
}
|
||||
};
|
||||
const authorPrefersDark = false;
|
||||
const queryPrefersDark = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
const darkModeDefault = queryPrefersDark.matches;
|
||||
document.querySelector('link.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
|
||||
document.querySelector('link#quarto-text-highlighting-styles.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
|
||||
document.querySelector('link#quarto-bootstrap.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
|
||||
let localAlternateSentinel = darkModeDefault ? 'alternate' : 'default';
|
||||
// Dark / light mode switch
|
||||
window.quartoToggleColorScheme = () => {
|
||||
// Read the current dark / light value
|
||||
let toAlternate = !window.hasAlternateSentinel();
|
||||
let toAlternate = !hasAlternateSentinel();
|
||||
toggleColorMode(toAlternate);
|
||||
setStyleSentinel(toAlternate);
|
||||
toggleGiscusIfUsed(toAlternate, darkModeDefault);
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
};
|
||||
queryPrefersDark.addEventListener("change", e => {
|
||||
if(window.localStorage.getItem("quarto-color-scheme") !== null)
|
||||
@ -241,7 +246,7 @@ ul.task-list li input[type="checkbox"] {
|
||||
toggleGiscusIfUsed(alternate, darkModeDefault);
|
||||
});
|
||||
// Switch to dark mode if need be
|
||||
if (window.hasAlternateSentinel()) {
|
||||
if (hasAlternateSentinel()) {
|
||||
toggleColorMode(true);
|
||||
} else {
|
||||
toggleColorMode(false);
|
||||
@ -253,6 +258,8 @@ ul.task-list li input[type="checkbox"] {
|
||||
<nav class="navbar navbar-expand-lg " data-bs-theme="dark">
|
||||
<div class="navbar-container container-fluid">
|
||||
<div class="navbar-brand-container mx-auto">
|
||||
<a href="../../index.html" class="navbar-brand navbar-brand-logo">
|
||||
</a>
|
||||
<a class="navbar-brand" href="../../index.html">
|
||||
<span class="navbar-title">Nicole Dresselhaus</span>
|
||||
</a>
|
||||
@ -264,12 +271,12 @@ ul.task-list li input[type="checkbox"] {
|
||||
<div class="collapse navbar-collapse" id="navbarCollapse">
|
||||
<ul class="navbar-nav navbar-nav-scroll me-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../index.html"> <i class="bi bi-house" role="img">
|
||||
<a class="nav-link active" href="../../index.html" aria-current="page"> <i class="bi bi-house" role="img">
|
||||
</i>
|
||||
<span class="menu-text">Home</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="../../About/index.html" aria-current="page"> <i class="bi bi-file-person" role="img">
|
||||
<a class="nav-link" href="../../About/index.html"> <i class="bi bi-file-person" role="img">
|
||||
</i>
|
||||
<span class="menu-text">About</span></a>
|
||||
</li>
|
||||
@ -307,6 +314,10 @@ ul.task-list li input[type="checkbox"] {
|
||||
<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-article page-navbar">
|
||||
<!-- sidebar -->
|
||||
<nav id="quarto-sidebar" class="sidebar collapse collapse-horizontal quarto-sidebar-collapse-item sidebar-navigation docked overflow-auto">
|
||||
<div class="pt-lg-2 mt-2 text-left sidebar-header">
|
||||
<a href="../../index.html" class="sidebar-logo-link">
|
||||
</a>
|
||||
</div>
|
||||
<div class="sidebar-menu-container">
|
||||
<ul class="list-unstyled mt-1">
|
||||
<li class="sidebar-item sidebar-item-section">
|
||||
@ -350,12 +361,6 @@ ul.task-list li input[type="checkbox"] {
|
||||
<a href="../../Writing/Obsidian-RAG.html" class="sidebar-item-text sidebar-link">
|
||||
<span class="menu-text">RAG für eine Obsidian-Wissensdatenbank: Technische Ansätze</span></a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="../../Obsidian-Articles/Artikelbewertung durch LLM.html" class="sidebar-item-text sidebar-link">
|
||||
<span class="menu-text">Artikelbewertung durch ein Large Language Model (LLM) - Ein Beispiel aus der Praxis</span></a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
@ -666,7 +671,7 @@ ul.task-list li input[type="checkbox"] {
|
||||
a.appendChild(i);
|
||||
window.document.body.appendChild(a);
|
||||
}
|
||||
window.setColorSchemeToggle(window.hasAlternateSentinel())
|
||||
setColorSchemeToggle(hasAlternateSentinel())
|
||||
const icon = "";
|
||||
const anchorJS = new window.AnchorJS();
|
||||
anchorJS.options = {
|
||||
|
199
dist/Coding/Haskell/Lenses.html
vendored
199
dist/Coding/Haskell/Lenses.html
vendored
@ -2,7 +2,7 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="generator" content="quarto-1.7.23">
|
||||
<meta name="generator" content="quarto-1.8.17">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||||
|
||||
@ -68,17 +68,19 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<meta name="quarto:offset" content="../../">
|
||||
<script src="../../site_libs/quarto-html/quarto.js" type="module"></script>
|
||||
<script src="../../site_libs/quarto-html/tabsets/tabsets.js" type="module"></script>
|
||||
<script src="../../site_libs/quarto-html/axe/axe-check.js" type="module"></script>
|
||||
<script src="../../site_libs/quarto-html/popper.min.js"></script>
|
||||
<script src="../../site_libs/quarto-html/tippy.umd.min.js"></script>
|
||||
<script src="../../site_libs/quarto-html/anchor.min.js"></script>
|
||||
<link href="../../site_libs/quarto-html/tippy.css" rel="stylesheet">
|
||||
<link href="../../site_libs/quarto-html/quarto-syntax-highlighting-dark-2c84ecb840a13f4c7993f9e5648f0c14.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles">
|
||||
<link href="../../site_libs/quarto-html/quarto-syntax-highlighting-6cf5824034cebd0380a5b9c74c43f006.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles">
|
||||
<link href="../../site_libs/quarto-html/quarto-syntax-highlighting-ff1c8a91a872873ab9706226229f9e30.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles">
|
||||
<link href="../../site_libs/quarto-html/quarto-syntax-highlighting-dark-04b38c9dba5d7c0f1fe2b621b39e7e62.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles">
|
||||
<link href="../../site_libs/quarto-html/quarto-syntax-highlighting-ff1c8a91a872873ab9706226229f9e30.css" rel="stylesheet" class="quarto-color-scheme-extra" id="quarto-text-highlighting-styles">
|
||||
<script src="../../site_libs/bootstrap/bootstrap.min.js"></script>
|
||||
<link href="../../site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
|
||||
<link href="../../site_libs/bootstrap/bootstrap-ec71cb1e120c0dd41819aca960e74e38.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light">
|
||||
<link href="../../site_libs/bootstrap/bootstrap-dark-716ed94a23403968eaa6fe981e0cbf91.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="dark">
|
||||
<link href="../../site_libs/bootstrap/bootstrap-ec71cb1e120c0dd41819aca960e74e38.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme-extra" id="quarto-bootstrap" data-mode="light">
|
||||
<link href="../../site_libs/bootstrap/bootstrap-9b56b6674ace31b1957ea5f5ef42286f.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light">
|
||||
<link href="../../site_libs/bootstrap/bootstrap-dark-3c8015a3c2181875b3e8a350495bd83c.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="dark">
|
||||
<link href="../../site_libs/bootstrap/bootstrap-9b56b6674ace31b1957ea5f5ef42286f.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme-extra" id="quarto-bootstrap" data-mode="light">
|
||||
<script id="quarto-search-options" type="application/json">{
|
||||
"location": "navbar",
|
||||
"copy-button": false,
|
||||
@ -131,7 +133,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
toggleBodyColorMode(bsSheetEl);
|
||||
}
|
||||
}
|
||||
window.setColorSchemeToggle = (alternate) => {
|
||||
const setColorSchemeToggle = (alternate) => {
|
||||
const toggles = window.document.querySelectorAll('.quarto-color-scheme-toggle');
|
||||
for (let i=0; i < toggles.length; i++) {
|
||||
const toggle = toggles[i];
|
||||
@ -164,7 +166,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
}
|
||||
manageTransitions('#quarto-margin-sidebar .nav-link', true);
|
||||
// Switch the toggles
|
||||
window.setColorSchemeToggle(alternate)
|
||||
setColorSchemeToggle(alternate)
|
||||
// Hack to workaround the fact that safari doesn't
|
||||
// properly recolor the scrollbar when toggling (#1455)
|
||||
if (navigator.userAgent.indexOf('Safari') > 0 && navigator.userAgent.indexOf('Chrome') == -1) {
|
||||
@ -204,7 +206,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
const isFileUrl = () => {
|
||||
return window.location.protocol === 'file:';
|
||||
}
|
||||
window.hasAlternateSentinel = () => {
|
||||
const hasAlternateSentinel = () => {
|
||||
let styleSentinel = getColorSchemeSentinel();
|
||||
if (styleSentinel !== null) {
|
||||
return styleSentinel === "alternate";
|
||||
@ -232,7 +234,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
const baseTheme = document.querySelector('#giscus-base-theme')?.value ?? 'light';
|
||||
const alternateTheme = document.querySelector('#giscus-alt-theme')?.value ?? 'dark';
|
||||
let newTheme = '';
|
||||
if(darkModeDefault) {
|
||||
if(authorPrefersDark) {
|
||||
newTheme = isAlternate ? baseTheme : alternateTheme;
|
||||
} else {
|
||||
newTheme = isAlternate ? alternateTheme : baseTheme;
|
||||
@ -255,17 +257,20 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
changeGiscusTheme();
|
||||
}
|
||||
};
|
||||
const authorPrefersDark = false;
|
||||
const queryPrefersDark = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
const darkModeDefault = queryPrefersDark.matches;
|
||||
document.querySelector('link.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
|
||||
document.querySelector('link#quarto-text-highlighting-styles.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
|
||||
document.querySelector('link#quarto-bootstrap.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
|
||||
let localAlternateSentinel = darkModeDefault ? 'alternate' : 'default';
|
||||
// Dark / light mode switch
|
||||
window.quartoToggleColorScheme = () => {
|
||||
// Read the current dark / light value
|
||||
let toAlternate = !window.hasAlternateSentinel();
|
||||
let toAlternate = !hasAlternateSentinel();
|
||||
toggleColorMode(toAlternate);
|
||||
setStyleSentinel(toAlternate);
|
||||
toggleGiscusIfUsed(toAlternate, darkModeDefault);
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
};
|
||||
queryPrefersDark.addEventListener("change", e => {
|
||||
if(window.localStorage.getItem("quarto-color-scheme") !== null)
|
||||
@ -276,7 +281,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
toggleGiscusIfUsed(alternate, darkModeDefault);
|
||||
});
|
||||
// Switch to dark mode if need be
|
||||
if (window.hasAlternateSentinel()) {
|
||||
if (hasAlternateSentinel()) {
|
||||
toggleColorMode(true);
|
||||
} else {
|
||||
toggleColorMode(false);
|
||||
@ -288,6 +293,8 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<nav class="navbar navbar-expand-lg " data-bs-theme="dark">
|
||||
<div class="navbar-container container-fluid">
|
||||
<div class="navbar-brand-container mx-auto">
|
||||
<a href="../../index.html" class="navbar-brand navbar-brand-logo">
|
||||
</a>
|
||||
<a class="navbar-brand" href="../../index.html">
|
||||
<span class="navbar-title">Nicole Dresselhaus</span>
|
||||
</a>
|
||||
@ -299,12 +306,12 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<div class="collapse navbar-collapse" id="navbarCollapse">
|
||||
<ul class="navbar-nav navbar-nav-scroll me-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../index.html"> <i class="bi bi-house" role="img">
|
||||
<a class="nav-link active" href="../../index.html" aria-current="page"> <i class="bi bi-house" role="img">
|
||||
</i>
|
||||
<span class="menu-text">Home</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="../../About/index.html" aria-current="page"> <i class="bi bi-file-person" role="img">
|
||||
<a class="nav-link" href="../../About/index.html"> <i class="bi bi-file-person" role="img">
|
||||
</i>
|
||||
<span class="menu-text">About</span></a>
|
||||
</li>
|
||||
@ -342,6 +349,10 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-article page-navbar">
|
||||
<!-- sidebar -->
|
||||
<nav id="quarto-sidebar" class="sidebar collapse collapse-horizontal quarto-sidebar-collapse-item sidebar-navigation docked overflow-auto">
|
||||
<div class="pt-lg-2 mt-2 text-left sidebar-header">
|
||||
<a href="../../index.html" class="sidebar-logo-link">
|
||||
</a>
|
||||
</div>
|
||||
<div class="sidebar-menu-container">
|
||||
<ul class="list-unstyled mt-1">
|
||||
<li class="sidebar-item sidebar-item-section">
|
||||
@ -385,12 +396,6 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<a href="../../Writing/Obsidian-RAG.html" class="sidebar-item-text sidebar-link">
|
||||
<span class="menu-text">RAG für eine Obsidian-Wissensdatenbank: Technische Ansätze</span></a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="../../Obsidian-Articles/Artikelbewertung durch LLM.html" class="sidebar-item-text sidebar-link">
|
||||
<span class="menu-text">Artikelbewertung durch ein Large Language Model (LLM) - Ein Beispiel aus der Praxis</span></a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
@ -691,7 +696,7 @@ kann. Also einfachen Datenstruktur kann man einen Record mit der entsprechenden<
|
||||
Syntax nehmen.</p>
|
||||
<section id="beispiel" class="level3">
|
||||
<h3 class="anchored" data-anchor-id="beispiel">Beispiel</h3>
|
||||
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Person</span> <span class="ot">=</span> <span class="dt">P</span> {<span class="ot"> name ::</span> <span class="dt">String</span></span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Person</span> <span class="ot">=</span> <span class="dt">P</span> {<span class="ot"> name ::</span> <span class="dt">String</span></span>
|
||||
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a> ,<span class="ot"> addr ::</span> <span class="dt">Address</span></span>
|
||||
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> ,<span class="ot"> salary ::</span> <span class="dt">Int</span> }</span>
|
||||
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Address</span> <span class="ot">=</span> <span class="dt">A</span> {<span class="ot"> road ::</span> <span class="dt">String</span></span>
|
||||
@ -705,7 +710,7 @@ Syntax nehmen.</p>
|
||||
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="ot"> setPostcode ::</span> <span class="dt">String</span> <span class="ot">-></span> <span class="dt">Person</span> <span class="ot">-></span> <span class="dt">Person</span></span>
|
||||
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a> setPostcode pc p</span>
|
||||
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a> <span class="ot">=</span> p { addr <span class="ot">=</span> addr p { postcode <span class="ot">=</span> pc } }</span>
|
||||
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a> <span class="co">-- update of a record inside a record</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a> <span class="co">-- update of a record inside a record</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
</section>
|
||||
<section id="problem" class="level3">
|
||||
<h3 class="anchored" data-anchor-id="problem">Problem</h3>
|
||||
@ -720,7 +725,7 @@ interessiert sind</li>
|
||||
</section>
|
||||
<section id="was-wir-gern-hätten" class="level3">
|
||||
<h3 class="anchored" data-anchor-id="was-wir-gern-hätten">Was wir gern hätten</h3>
|
||||
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Person</span> <span class="ot">=</span> <span class="dt">P</span> {<span class="ot"> name ::</span> <span class="dt">String</span></span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Person</span> <span class="ot">=</span> <span class="dt">P</span> {<span class="ot"> name ::</span> <span class="dt">String</span></span>
|
||||
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a> ,<span class="ot"> addr ::</span> <span class="dt">Address</span></span>
|
||||
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a> ,<span class="ot"> salary ::</span> <span class="dt">Int</span> }</span>
|
||||
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="co">-- a lens for each field</span></span>
|
||||
@ -731,12 +736,12 @@ interessiert sind</li>
|
||||
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a><span class="ot">view ::</span> <span class="dt">Lens'</span> s a <span class="ot">-></span> s <span class="ot">-></span> a</span>
|
||||
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a><span class="ot">set ::</span> <span class="dt">Lens'</span> s a <span class="ot">-></span> a <span class="ot">-></span> s <span class="ot">-></span> s</span>
|
||||
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a><span class="co">-- lens-composition</span></span>
|
||||
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a><span class="ot">composeL ::</span> <span class="dt">Lens'</span> s1 s2 <span class="ot">-></span> <span class="dt">Lens</span> s2 a <span class="ot">-></span> <span class="dt">Lens'</span> s1 a</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a><span class="ot">composeL ::</span> <span class="dt">Lens'</span> s1 s2 <span class="ot">-></span> <span class="dt">Lens</span> s2 a <span class="ot">-></span> <span class="dt">Lens'</span> s1 a</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
</section>
|
||||
<section id="wie-uns-das-hilft" class="level3">
|
||||
<h3 class="anchored" data-anchor-id="wie-uns-das-hilft">Wie uns das hilft</h3>
|
||||
<p>Mit diesen Dingen (wenn wir sie hätten) könnte man dann</p>
|
||||
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Person</span> <span class="ot">=</span> <span class="dt">P</span> {<span class="ot"> name ::</span> <span class="dt">String</span></span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Person</span> <span class="ot">=</span> <span class="dt">P</span> {<span class="ot"> name ::</span> <span class="dt">String</span></span>
|
||||
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a> ,<span class="ot"> addr ::</span> <span class="dt">Address</span></span>
|
||||
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a> ,<span class="ot"> salary ::</span> <span class="dt">Int</span> }</span>
|
||||
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Address</span> <span class="ot">=</span> <span class="dt">A</span> {<span class="ot"> road ::</span> <span class="dt">String</span></span>
|
||||
@ -744,7 +749,7 @@ interessiert sind</li>
|
||||
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a> ,<span class="ot"> postcode ::</span> <span class="dt">String</span> }</span>
|
||||
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="ot">setPostcode ::</span> <span class="dt">String</span> <span class="ot">-></span> <span class="dt">Person</span> <span class="ot">-></span> <span class="dt">Person</span></span>
|
||||
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>setPostcode pc p</span>
|
||||
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a> <span class="ot">=</span> set (laddr <span class="ot">`composeL`</span> lpostcode) pc p</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a> <span class="ot">=</span> set (laddr <span class="ot">`composeL`</span> lpostcode) pc p</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>machen und wäre fertig.</p>
|
||||
</section>
|
||||
</section>
|
||||
@ -752,12 +757,12 @@ interessiert sind</li>
|
||||
<h2 class="anchored" data-anchor-id="trivialer-ansatz">Trivialer Ansatz</h2>
|
||||
<section id="gettersetter-also-lens-methoden" class="level3">
|
||||
<h3 class="anchored" data-anchor-id="gettersetter-also-lens-methoden">Getter/Setter also Lens-Methoden</h3>
|
||||
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">LensR</span> s a <span class="ot">=</span> <span class="dt">L</span> {<span class="ot"> viewR ::</span> s <span class="ot">-></span> a</span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">LensR</span> s a <span class="ot">=</span> <span class="dt">L</span> {<span class="ot"> viewR ::</span> s <span class="ot">-></span> a</span>
|
||||
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a> ,<span class="ot"> setR ::</span> a <span class="ot">-></span> s <span class="ot">-></span> s }</span>
|
||||
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>composeL (<span class="dt">L</span> v1 u1) (<span class="dt">L</span> v2 u2)</span>
|
||||
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a> <span class="ot">=</span> <span class="dt">L</span> (\s <span class="ot">-></span> v2 (v1 s))</span>
|
||||
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a> (\a s <span class="ot">-></span> u1 (u2 a (v1 s)) s)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a> (\a s <span class="ot">-></span> u1 (u2 a (v1 s)) s)</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
</section>
|
||||
<section id="wieso-ist-das-schlecht" class="level3">
|
||||
<h3 class="anchored" data-anchor-id="wieso-ist-das-schlecht">Wieso ist das schlecht?</h3>
|
||||
@ -766,110 +771,110 @@ interessiert sind</li>
|
||||
</ul>
|
||||
<p>Auslesen traversiert die Datenstruktur, dann wird die Function angewendet und<br>
|
||||
zum setzen wird die Datenstruktur erneut traversiert:</p>
|
||||
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ot">over ::</span> <span class="dt">LensR</span> s a <span class="ot">-></span> (a <span class="ot">-></span> a) <span class="ot">-></span> s <span class="ot">-></span> s</span>
|
||||
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>over ln f s <span class="ot">=</span> setR l (f (viewR l s)) s</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ot">over ::</span> <span class="dt">LensR</span> s a <span class="ot">-></span> (a <span class="ot">-></span> a) <span class="ot">-></span> s <span class="ot">-></span> s</span>
|
||||
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>over ln f s <span class="ot">=</span> setR l (f (viewR l s)) s</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<ul>
|
||||
<li>Lösung: modify-funktion hinzufügen</li>
|
||||
</ul>
|
||||
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">LensR</span> s a</span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">LensR</span> s a</span>
|
||||
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a> <span class="ot">=</span> <span class="dt">L</span> {<span class="ot"> viewR ::</span> s <span class="ot">-></span> a</span>
|
||||
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a> ,<span class="ot"> setR ::</span> a <span class="ot">-></span> s <span class="ot">-></span> s</span>
|
||||
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a> ,<span class="ot"> mod ::</span> (a<span class="ot">-></span>a) <span class="ot">-></span> s <span class="ot">-></span> s</span>
|
||||
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a> ,<span class="ot"> modM ::</span> (a<span class="ot">-></span><span class="dt">Maybe</span> a) <span class="ot">-></span> s <span class="ot">-></span> <span class="dt">Maybe</span> s</span>
|
||||
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a> ,<span class="ot"> modIO ::</span> (a<span class="ot">-></span><span class="dt">IO</span> a) <span class="ot">-></span> s <span class="ot">-></span> <span class="dt">IO</span> s }</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a> ,<span class="ot"> modIO ::</span> (a<span class="ot">-></span><span class="dt">IO</span> a) <span class="ot">-></span> s <span class="ot">-></span> <span class="dt">IO</span> s }</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Neues Problem: Für jeden Spezialfall muss die Lens erweitert werden.</p>
|
||||
</section>
|
||||
<section id="something-in-common" class="level3">
|
||||
<h3 class="anchored" data-anchor-id="something-in-common">Something in common</h3>
|
||||
<p>Man kann alle Monaden abstrahieren. Functor reicht schon:</p>
|
||||
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">LensR</span> s a</span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">LensR</span> s a</span>
|
||||
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a> <span class="ot">=</span> <span class="dt">L</span> {<span class="ot"> viewR ::</span> s <span class="ot">-></span> a</span>
|
||||
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a> ,<span class="ot"> setR ::</span> a <span class="ot">-></span> s <span class="ot">-></span> s</span>
|
||||
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a> ,<span class="ot"> mod ::</span> (a<span class="ot">-></span>a) <span class="ot">-></span> s <span class="ot">-></span> s</span>
|
||||
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a> ,<span class="ot"> modF ::</span> <span class="dt">Functor</span> f <span class="ot">=></span> (a<span class="ot">-></span>f a) <span class="ot">-></span> s <span class="ot">-></span> f s }</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a> ,<span class="ot"> modF ::</span> <span class="dt">Functor</span> f <span class="ot">=></span> (a<span class="ot">-></span>f a) <span class="ot">-></span> s <span class="ot">-></span> f s }</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Idee: Die 3 darüberliegenden durch modF ausdrücken.</p>
|
||||
</section>
|
||||
<section id="typ-einer-lens" class="level3">
|
||||
<h3 class="anchored" data-anchor-id="typ-einer-lens">Typ einer Lens</h3>
|
||||
<p>Wenn man das berücksichtigt, dann hat einen Lens folgenden Typ:</p>
|
||||
<div class="sourceCode" id="cb8"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Lens'</span> s a <span class="ot">=</span> <span class="kw">forall</span> f<span class="op">.</span> <span class="dt">Functor</span> f</span>
|
||||
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a> <span class="ot">=></span> (a <span class="ot">-></span> f a) <span class="ot">-></span> s <span class="ot">-></span> f s</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Lens'</span> s a <span class="ot">=</span> <span class="kw">forall</span> f<span class="op">.</span> <span class="dt">Functor</span> f</span>
|
||||
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a> <span class="ot">=></span> (a <span class="ot">-></span> f a) <span class="ot">-></span> s <span class="ot">-></span> f s</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Allerdings haben wir dann noch unseren getter/setter:</p>
|
||||
<div class="sourceCode" id="cb9"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">LensR</span> s a <span class="ot">=</span> <span class="dt">L</span> {<span class="ot"> viewR ::</span> s <span class="ot">-></span> a</span>
|
||||
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a> ,<span class="ot"> setR ::</span> a <span class="ot">-></span> s <span class="ot">-></span> s }</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb9"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">LensR</span> s a <span class="ot">=</span> <span class="dt">L</span> {<span class="ot"> viewR ::</span> s <span class="ot">-></span> a</span>
|
||||
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a> ,<span class="ot"> setR ::</span> a <span class="ot">-></span> s <span class="ot">-></span> s }</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Stellt sich raus: Die sind isomorph! Auch wenn die von den Typen her komplett<br>
|
||||
anders aussehen.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="benutzen-einer-lens-also-setter" class="level2">
|
||||
<h2 class="anchored" data-anchor-id="benutzen-einer-lens-also-setter">Benutzen einer Lens also Setter</h2>
|
||||
<div class="sourceCode" id="cb10"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ot">set ::</span> <span class="dt">Lens'</span> s a <span class="ot">-></span> (a <span class="ot">-></span> s <span class="ot">-></span> s)</span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb10"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ot">set ::</span> <span class="dt">Lens'</span> s a <span class="ot">-></span> (a <span class="ot">-></span> s <span class="ot">-></span> s)</span>
|
||||
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>set ln a s <span class="ot">=</span> <span class="op">--...</span>umm<span class="op">...</span></span>
|
||||
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="op">--:</span>t ln <span class="ot">=></span> (a <span class="ot">-></span> f a) <span class="ot">-></span> s <span class="ot">-></span> f s</span>
|
||||
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="co">-- => get s out of f s to return it</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="co">-- => get s out of f s to return it</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Wir können für f einfach die “Identity”-Monade nehmen, die wir nachher wegcasten<br>
|
||||
können.</p>
|
||||
<div class="sourceCode" id="cb11"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">Identity</span> a <span class="ot">=</span> <span class="dt">Identity</span> a</span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb11"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">Identity</span> a <span class="ot">=</span> <span class="dt">Identity</span> a</span>
|
||||
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="co">-- Id :: a -> Identity a</span></span>
|
||||
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a><span class="ot">runIdentity ::</span> <span class="dt">Identity</span> s <span class="ot">-></span> s</span>
|
||||
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>runIdentity (<span class="dt">Identity</span> x) <span class="ot">=</span> x</span>
|
||||
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Functor</span> <span class="dt">Identity</span> <span class="kw">where</span></span>
|
||||
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a> <span class="fu">fmap</span> f (<span class="dt">Identity</span> x) <span class="ot">=</span> <span class="dt">Identity</span> (f x)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a> <span class="fu">fmap</span> f (<span class="dt">Identity</span> x) <span class="ot">=</span> <span class="dt">Identity</span> (f x)</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>somit ist set einfach nur</p>
|
||||
<div class="sourceCode" id="cb12"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="ot">set ::</span> <span class="dt">Lens'</span> s a <span class="ot">-></span> (a <span class="ot">-></span> s <span class="ot">-></span> s)</span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb12"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="ot">set ::</span> <span class="dt">Lens'</span> s a <span class="ot">-></span> (a <span class="ot">-></span> s <span class="ot">-></span> s)</span>
|
||||
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>set ln x s</span>
|
||||
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a> <span class="ot">=</span> runIdentity (ls set_fld s)</span>
|
||||
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
|
||||
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a><span class="ot"> set_fld ::</span> a <span class="ot">-></span> <span class="dt">Identity</span> a</span>
|
||||
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a> set_fld _ <span class="ot">=</span> <span class="dt">Identity</span> x</span>
|
||||
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a> <span class="co">-- a was the OLD value.</span></span>
|
||||
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a> <span class="co">-- We throw that away and set the new value</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a> <span class="co">-- We throw that away and set the new value</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>oder kürzer (für nerds wie den Author der Lens-Lib)</p>
|
||||
<div class="sourceCode" id="cb13"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="ot">set ::</span> <span class="dt">Lens'</span> s a <span class="ot">-></span> (a <span class="ot">-></span> s <span class="ot">-></span> s)</span>
|
||||
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>set ln x <span class="ot">=</span> runIdentity <span class="op">.</span> ln (<span class="dt">Identity</span> <span class="op">.</span> <span class="fu">const</span> x)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb13"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="ot">set ::</span> <span class="dt">Lens'</span> s a <span class="ot">-></span> (a <span class="ot">-></span> s <span class="ot">-></span> s)</span>
|
||||
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>set ln x <span class="ot">=</span> runIdentity <span class="op">.</span> ln (<span class="dt">Identity</span> <span class="op">.</span> <span class="fu">const</span> x)</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
</section>
|
||||
<section id="benutzen-einer-lens-also-modify" class="level2">
|
||||
<h2 class="anchored" data-anchor-id="benutzen-einer-lens-also-modify">Benutzen einer Lens also Modify</h2>
|
||||
<p>Dasselbe wie Set, nur dass wir den Parameter nicht entsorgen, sondern in die<br>
|
||||
mitgelieferte Function stopfen.</p>
|
||||
<div class="sourceCode" id="cb14"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="ot">over ::</span> <span class="dt">Lens'</span> s a <span class="ot">-></span> (a <span class="ot">-></span> a) <span class="ot">-></span> s <span class="ot">-></span> s</span>
|
||||
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>over ln f <span class="ot">=</span> runIdentity <span class="op">.</span> ln (<span class="dt">Identity</span> <span class="op">.</span> f)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb14"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="ot">over ::</span> <span class="dt">Lens'</span> s a <span class="ot">-></span> (a <span class="ot">-></span> a) <span class="ot">-></span> s <span class="ot">-></span> s</span>
|
||||
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>over ln f <span class="ot">=</span> runIdentity <span class="op">.</span> ln (<span class="dt">Identity</span> <span class="op">.</span> f)</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
</section>
|
||||
<section id="benutzen-einer-lens-also-getter" class="level2">
|
||||
<h2 class="anchored" data-anchor-id="benutzen-einer-lens-also-getter">Benutzen einer Lens also Getter</h2>
|
||||
<div class="sourceCode" id="cb15"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="ot">view ::</span> <span class="dt">Lens'</span> s a <span class="ot">-></span> (s <span class="ot">-></span> a)</span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb15"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="ot">view ::</span> <span class="dt">Lens'</span> s a <span class="ot">-></span> (s <span class="ot">-></span> a)</span>
|
||||
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>view ln s <span class="ot">=</span> <span class="op">--...</span>umm<span class="op">...</span></span>
|
||||
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a><span class="op">--:</span>t ln <span class="ot">=></span> (a <span class="ot">-></span> f a) <span class="ot">-></span> s <span class="ot">-></span> f s</span>
|
||||
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a><span class="co">-- => get a out of the (f s) return-value</span></span>
|
||||
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a><span class="co">-- Wait, WHAT?</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a><span class="co">-- Wait, WHAT?</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Auch hier gibt es einen netten Funktor. Wir packen das “a” einfach in das “f”<br>
|
||||
und werfen das “s” am End weg.</p>
|
||||
<div class="sourceCode" id="cb16"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">Const</span> v a <span class="ot">=</span> <span class="dt">Const</span> v</span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb16"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">Const</span> v a <span class="ot">=</span> <span class="dt">Const</span> v</span>
|
||||
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a><span class="ot">getConst ::</span> <span class="dt">Const</span> v a <span class="ot">-></span> v</span>
|
||||
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>getConst (<span class="dt">Const</span> x) <span class="ot">=</span> x</span>
|
||||
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Functor</span> (<span class="dt">Const</span> v) <span class="kw">where</span></span>
|
||||
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a> <span class="fu">fmap</span> f (<span class="dt">Const</span> x) <span class="ot">=</span> <span class="dt">Const</span> x</span>
|
||||
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a> <span class="co">-- throw f away. Nothing changes our const!</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a> <span class="co">-- throw f away. Nothing changes our const!</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>somit ergibt sich</p>
|
||||
<div class="sourceCode" id="cb17"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="ot">view ::</span> <span class="dt">Lens'</span> s a <span class="ot">-></span> (s <span class="ot">-></span> a)</span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb17"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="ot">view ::</span> <span class="dt">Lens'</span> s a <span class="ot">-></span> (s <span class="ot">-></span> a)</span>
|
||||
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>view ln s</span>
|
||||
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a> <span class="ot">=</span> getConst (ln <span class="dt">Const</span> s)</span>
|
||||
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a> <span class="co">-- Const :: s -> Const a s</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a> <span class="co">-- Const :: s -> Const a s</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>oder nerdig</p>
|
||||
<div class="sourceCode" id="cb18"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="ot">view ::</span> <span class="dt">Lens'</span> s a <span class="ot">-></span> (s <span class="ot">-></span> a)</span>
|
||||
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>view ln <span class="ot">=</span> getConst <span class="op">.</span> ln <span class="dt">Const</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb18"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="ot">view ::</span> <span class="dt">Lens'</span> s a <span class="ot">-></span> (s <span class="ot">-></span> a)</span>
|
||||
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>view ln <span class="ot">=</span> getConst <span class="op">.</span> ln <span class="dt">Const</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
</section>
|
||||
<section id="lenses-bauen" class="level2">
|
||||
<h2 class="anchored" data-anchor-id="lenses-bauen">Lenses bauen</h2>
|
||||
<p>Nochmal kurz der Typ:</p>
|
||||
<div class="sourceCode" id="cb19"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Lens'</span> s a <span class="ot">=</span> <span class="kw">forall</span> f<span class="op">.</span> <span class="dt">Functor</span> f</span>
|
||||
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a> <span class="ot">=></span> (a <span class="ot">-></span> f a) <span class="ot">-></span> s <span class="ot">-></span> f s</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb19"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Lens'</span> s a <span class="ot">=</span> <span class="kw">forall</span> f<span class="op">.</span> <span class="dt">Functor</span> f</span>
|
||||
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a> <span class="ot">=></span> (a <span class="ot">-></span> f a) <span class="ot">-></span> s <span class="ot">-></span> f s</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Für unser Personen-Beispiel vom Anfang:</p>
|
||||
<div class="sourceCode" id="cb20"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Person</span> <span class="ot">=</span> <span class="dt">P</span> {<span class="ot"> _name ::</span> <span class="dt">String</span>,<span class="ot"> _salary ::</span> <span class="dt">Int</span> }</span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb20"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Person</span> <span class="ot">=</span> <span class="dt">P</span> {<span class="ot"> _name ::</span> <span class="dt">String</span>,<span class="ot"> _salary ::</span> <span class="dt">Int</span> }</span>
|
||||
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a><span class="ot">name ::</span> <span class="dt">Lens'</span> <span class="dt">Person</span> <span class="dt">String</span></span>
|
||||
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a><span class="co">-- name :: Functor f => (String -> f String)</span></span>
|
||||
@ -879,15 +884,15 @@ und werfen das “s” am End weg.</p>
|
||||
<span id="cb20-8"><a href="#cb20-8" aria-hidden="true" tabindex="-1"></a> <span class="ot">=</span> <span class="fu">fmap</span> (\n' <span class="ot">-></span> <span class="dt">P</span> n' s) (elt_fn n)</span>
|
||||
<span id="cb20-9"><a href="#cb20-9" aria-hidden="true" tabindex="-1"></a><span class="co">-- fmap :: Functor f => (a->b) -> f a -> f b - der Funktor, der alles verknüpft</span></span>
|
||||
<span id="cb20-10"><a href="#cb20-10" aria-hidden="true" tabindex="-1"></a><span class="co">-- \n' -> .. :: String -> Person - Funktion um das Element zu lokalisieren (WO wird ersetzt/gelesen/...)</span></span>
|
||||
<span id="cb20-11"><a href="#cb20-11" aria-hidden="true" tabindex="-1"></a><span class="co">-- elt_fn n :: f String - Funktion um das Element zu verändern (setzen, ändern, ...)</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb20-11"><a href="#cb20-11" aria-hidden="true" tabindex="-1"></a><span class="co">-- elt_fn n :: f String - Funktion um das Element zu verändern (setzen, ändern, ...)</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Die Lambda-Funktion ersetzt einfach den Namen. Häufig sieht man auch</p>
|
||||
<div class="sourceCode" id="cb21"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a>name elt_fn (<span class="dt">P</span> n s)</span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb21"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a>name elt_fn (<span class="dt">P</span> n s)</span>
|
||||
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a> <span class="ot">=</span> (\n' <span class="ot">-></span> <span class="dt">P</span> n' s) <span class="op"><$></span> (elt_fn n)</span>
|
||||
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a><span class="co">-- | Focus | |Function|</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a><span class="co">-- | Focus | |Function|</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
</section>
|
||||
<section id="wie-funktioniert-das-intern" class="level2">
|
||||
<h2 class="anchored" data-anchor-id="wie-funktioniert-das-intern">Wie funktioniert das intern?</h2>
|
||||
<div class="sourceCode" id="cb22"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a>view name (<span class="dt">P</span> {_name<span class="ot">=</span><span class="st">"Fred"</span>, _salary<span class="ot">=</span><span class="dv">100</span>})</span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb22"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a>view name (<span class="dt">P</span> {_name<span class="ot">=</span><span class="st">"Fred"</span>, _salary<span class="ot">=</span><span class="dv">100</span>})</span>
|
||||
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a> <span class="co">-- inline view-function</span></span>
|
||||
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a><span class="ot">=</span> getConst (name <span class="dt">Const</span> (<span class="dt">P</span> {_name<span class="ot">=</span><span class="st">"Fred"</span>, _salary<span class="ot">=</span><span class="dv">100</span>})</span>
|
||||
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a> <span class="co">-- inline name</span></span>
|
||||
@ -895,7 +900,7 @@ und werfen das “s” am End weg.</p>
|
||||
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a> <span class="co">-- fmap f (Const x) = Const x - Definition von Const</span></span>
|
||||
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a><span class="ot">=</span> getConst (<span class="dt">Const</span> <span class="st">"Fred"</span>)</span>
|
||||
<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a> <span class="co">-- getConst (Const x) = x</span></span>
|
||||
<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a><span class="ot">=</span> <span class="st">"Fred"</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a><span class="ot">=</span> <span class="st">"Fred"</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Dieser Aufruf hat KEINE Runtime-Kosten, weil der Compiler direkt die Address des<br>
|
||||
Feldes einsetzen kann. Der gesamte Boilerplate-Code wird vom Compiler<br>
|
||||
wegoptimiert.</p>
|
||||
@ -923,15 +928,15 @@ Somit ist Lens-Composition einfach nur Function-Composition (.).</p>
|
||||
<section id="automatisieren-mit-template-haskell" class="level2">
|
||||
<h2 class="anchored" data-anchor-id="automatisieren-mit-template-haskell">Automatisieren mit Template-Haskell</h2>
|
||||
<p>Der Code um die Lenses zu bauen ist für records immer Identisch:</p>
|
||||
<div class="sourceCode" id="cb23"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Person</span> <span class="ot">=</span> <span class="dt">P</span> {<span class="ot"> _name ::</span> <span class="dt">String</span>,<span class="ot"> _salary ::</span> <span class="dt">Int</span> }</span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb23"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Person</span> <span class="ot">=</span> <span class="dt">P</span> {<span class="ot"> _name ::</span> <span class="dt">String</span>,<span class="ot"> _salary ::</span> <span class="dt">Int</span> }</span>
|
||||
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a><span class="ot">name ::</span> <span class="dt">Lens'</span> <span class="dt">Person</span> <span class="dt">String</span></span>
|
||||
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a>name elt_fn (<span class="dt">P</span> n s) <span class="ot">=</span> (\n' <span class="ot">-></span> <span class="dt">P</span> n' s) <span class="op"><$></span> (elt_fn n)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a>name elt_fn (<span class="dt">P</span> n s) <span class="ot">=</span> (\n' <span class="ot">-></span> <span class="dt">P</span> n' s) <span class="op"><$></span> (elt_fn n)</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Daher kann man einfach</p>
|
||||
<div class="sourceCode" id="cb24"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Lens.TH</span></span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb24"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Lens.TH</span></span>
|
||||
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Person</span> <span class="ot">=</span> <span class="dt">P</span> {<span class="ot"> _name ::</span> <span class="dt">String</span>,<span class="ot"> _salary ::</span> <span class="dt">Int</span> }</span>
|
||||
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a><span class="op">$</span>(makeLenses '<span class="dt">'Person</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a><span class="op">$</span>(makeLenses '<span class="dt">'Person</span>)</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>nehmen, was einem eine Lens für “name” und eine Lens für “salary” generiert.<br>
|
||||
Mit anderen Templates kann man auch weitere Dinge steuern (etwa wofür Lenses<br>
|
||||
generiert werden, welches Prefix (statt _) man haben will etc. pp.).</p>
|
||||
@ -939,7 +944,7 @@ generiert werden, welches Prefix (statt _) man haben will etc. pp.).</p>
|
||||
</section>
|
||||
<section id="lenses-für-den-beispielcode" class="level2">
|
||||
<h2 class="anchored" data-anchor-id="lenses-für-den-beispielcode">Lenses für den Beispielcode</h2>
|
||||
<div class="sourceCode" id="cb25"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Lens.TH</span></span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb25"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Lens.TH</span></span>
|
||||
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Person</span> <span class="ot">=</span> <span class="dt">P</span> {<span class="ot"> _name ::</span> <span class="dt">String</span></span>
|
||||
<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a> ,<span class="ot"> _addr ::</span> <span class="dt">Address</span></span>
|
||||
@ -952,11 +957,11 @@ generiert werden, welches Prefix (statt _) man haben will etc. pp.).</p>
|
||||
<span id="cb25-11"><a href="#cb25-11" aria-hidden="true" tabindex="-1"></a><span class="op">$</span>(makeLenses '<span class="dt">'Address</span>)</span>
|
||||
<span id="cb25-12"><a href="#cb25-12" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb25-13"><a href="#cb25-13" aria-hidden="true" tabindex="-1"></a><span class="ot">setPostcode ::</span> <span class="dt">String</span> <span class="ot">-></span> <span class="dt">Person</span> <span class="ot">-></span> <span class="dt">Person</span></span>
|
||||
<span id="cb25-14"><a href="#cb25-14" aria-hidden="true" tabindex="-1"></a>setPostcode pc p <span class="ot">=</span> set (addr <span class="op">.</span> postcode) pc p</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb25-14"><a href="#cb25-14" aria-hidden="true" tabindex="-1"></a>setPostcode pc p <span class="ot">=</span> set (addr <span class="op">.</span> postcode) pc p</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
</section>
|
||||
<section id="shortcuts-mit-line-noise" class="level2">
|
||||
<h2 class="anchored" data-anchor-id="shortcuts-mit-line-noise">Shortcuts mit “Line-Noise”</h2>
|
||||
<div class="sourceCode" id="cb26"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- ...</span></span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb26"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- ...</span></span>
|
||||
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a><span class="ot">setPostcode ::</span> <span class="dt">String</span> <span class="ot">-></span> <span class="dt">Person</span> <span class="ot">-></span> <span class="dt">Person</span></span>
|
||||
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a>setPostcode pc p <span class="ot">=</span> addr <span class="op">.</span> postcode <span class="op">.~</span> pc <span class="op">$</span> p</span>
|
||||
@ -964,7 +969,7 @@ generiert werden, welches Prefix (statt _) man haben will etc. pp.).</p>
|
||||
<span id="cb26-6"><a href="#cb26-6" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb26-7"><a href="#cb26-7" aria-hidden="true" tabindex="-1"></a><span class="ot">getPostcode ::</span> <span class="dt">Person</span> <span class="ot">-></span> <span class="dt">String</span></span>
|
||||
<span id="cb26-8"><a href="#cb26-8" aria-hidden="true" tabindex="-1"></a>getPostcode p <span class="ot">=</span> p <span class="op">^.</span> <span class="op">$</span> addr <span class="op">.</span> postcode</span>
|
||||
<span id="cb26-9"><a href="#cb26-9" aria-hidden="true" tabindex="-1"></a><span class="co">-- |from|get| Focus |</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb26-9"><a href="#cb26-9" aria-hidden="true" tabindex="-1"></a><span class="co">-- |from|get| Focus |</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Es gibt drölf-zillionen weitere Infix-Operatoren (für Folds,<br>
|
||||
Listenkonvertierungen, -traversierungen, …)</p>
|
||||
</section>
|
||||
@ -972,7 +977,7 @@ Listenkonvertierungen, -traversierungen, …)</p>
|
||||
<h2 class="anchored" data-anchor-id="virtuelle-felder">Virtuelle Felder</h2>
|
||||
<p>Man kann mit Lenses sogar Felder emulieren, die gar nicht da sind. Angenommen<br>
|
||||
folgender Code:</p>
|
||||
<div class="sourceCode" id="cb27"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Temp</span> <span class="ot">=</span> <span class="dt">T</span> {<span class="ot"> _fahrenheit ::</span> <span class="dt">Float</span> }</span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb27"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Temp</span> <span class="ot">=</span> <span class="dt">T</span> {<span class="ot"> _fahrenheit ::</span> <span class="dt">Float</span> }</span>
|
||||
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a><span class="op">$</span>(makeLenses '<span class="dt">'Temp</span>)</span>
|
||||
<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a><span class="co">-- liefert Lens: fahrenheit :: Lens Temp Float</span></span>
|
||||
@ -981,7 +986,7 @@ folgender Code:</p>
|
||||
<span id="cb27-7"><a href="#cb27-7" aria-hidden="true" tabindex="-1"></a>centigrade centi_fn (<span class="dt">T</span> faren)</span>
|
||||
<span id="cb27-8"><a href="#cb27-8" aria-hidden="true" tabindex="-1"></a> <span class="ot">=</span> (\centi' <span class="ot">-></span> <span class="dt">T</span> (cToF centi'))</span>
|
||||
<span id="cb27-9"><a href="#cb27-9" aria-hidden="true" tabindex="-1"></a> <span class="op"><$></span> (centi_fn (fToC faren))</span>
|
||||
<span id="cb27-10"><a href="#cb27-10" aria-hidden="true" tabindex="-1"></a><span class="co">-- cToF & fToC as Converter-Functions defined someplace else</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb27-10"><a href="#cb27-10" aria-hidden="true" tabindex="-1"></a><span class="co">-- cToF & fToC as Converter-Functions defined someplace else</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Hiermit kann man dann auch Funktionen, die auf Grad-Celsius rechnen auf Daten<br>
|
||||
anwenden, die eigenlich nur Fahrenheit speichern, aber eine Umrechnung<br>
|
||||
bereitstellen. Analog kann man auch einen Zeit-Datentypen definieren, der<br>
|
||||
@ -992,7 +997,7 @@ Minuten oder 37 Stunden ist)</p>
|
||||
<h2 class="anchored" data-anchor-id="non-record-strukturen">Non-Record Strukturen</h2>
|
||||
<p>Das ganze kann man auch parametrisieren und auf Non-Record-Strukturen anwenden.<br>
|
||||
Beispielhaft an einer Map verdeutlicht:</p>
|
||||
<div class="sourceCode" id="cb28"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- from Data.Lens.At</span></span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb28"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- from Data.Lens.At</span></span>
|
||||
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a><span class="ot">at ::</span> <span class="dt">Ord</span> k <span class="ot">=></span> k <span class="ot">-></span> <span class="dt">Lens'</span> (<span class="dt">Map</span> k v) (<span class="dt">Maybe</span> v)</span>
|
||||
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a><span class="co">-- oder identisch, wenn man die Lens' auflöst:</span></span>
|
||||
@ -1009,18 +1014,18 @@ Beispielhaft an einer Map verdeutlicht:</p>
|
||||
<span id="cb28-15"><a href="#cb28-15" aria-hidden="true" tabindex="-1"></a> <span class="dt">Nothing</span> <span class="ot">-></span> m</span>
|
||||
<span id="cb28-16"><a href="#cb28-16" aria-hidden="true" tabindex="-1"></a> <span class="dt">Just</span> _ <span class="ot">-></span> Map.delete k m</span>
|
||||
<span id="cb28-17"><a href="#cb28-17" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb28-18"><a href="#cb28-18" aria-hidden="true" tabindex="-1"></a><span class="co">-- mb_fn :: Maybe v -> f Maybe v</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb28-18"><a href="#cb28-18" aria-hidden="true" tabindex="-1"></a><span class="co">-- mb_fn :: Maybe v -> f Maybe v</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
</section>
|
||||
<section id="weitere-beispiele" class="level2">
|
||||
<h2 class="anchored" data-anchor-id="weitere-beispiele">Weitere Beispiele</h2>
|
||||
<ul>
|
||||
<li><p>Bitfields auf Strukturen die Bits haben (Ints, …) in Data.Bits.Lens</p></li>
|
||||
<li><p>Web-scraper in Package hexpat-lens</p>
|
||||
<div class="sourceCode" id="cb29"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a>p <span class="op">^..</span> _HTML' <span class="op">.</span> to allNodes</span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb29"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a>p <span class="op">^..</span> _HTML' <span class="op">.</span> to allNodes</span>
|
||||
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> <span class="fu">traverse</span> <span class="op">.</span> named <span class="st">"a"</span></span>
|
||||
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> <span class="fu">traverse</span> <span class="op">.</span> ix <span class="st">"href"</span></span>
|
||||
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> filtered isLocal</span>
|
||||
<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> to trimSpaces</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> to trimSpaces</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Zieht alle externen Links aus dem gegebenen HTML-Code in p um weitere ziele<br>
|
||||
fürs crawlen zu finden.</p></li>
|
||||
</ul>
|
||||
@ -1029,36 +1034,36 @@ fürs crawlen zu finden.</p></li>
|
||||
<h2 class="anchored" data-anchor-id="erweiterungen">Erweiterungen</h2>
|
||||
<p>Bisher hatten wir Lenses nur auf Funktoren F. Die nächstmächtigere Klasse ist<br>
|
||||
Applicative.</p>
|
||||
<div class="sourceCode" id="cb30"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Traversal'</span> s a <span class="ot">=</span> <span class="kw">forall</span> f<span class="op">.</span> <span class="dt">Applicative</span> f</span>
|
||||
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a> <span class="ot">=></span> (a <span class="ot">-></span> f a) <span class="ot">-></span> (s <span class="ot">-></span> f s)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb30"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Traversal'</span> s a <span class="ot">=</span> <span class="kw">forall</span> f<span class="op">.</span> <span class="dt">Applicative</span> f</span>
|
||||
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a> <span class="ot">=></span> (a <span class="ot">-></span> f a) <span class="ot">-></span> (s <span class="ot">-></span> f s)</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Da wir den Container identisch lassen (weder s noch a wurde angefasst) muss sich<br>
|
||||
etwas anderes ändern. Statt eines einzelnen Focus erhalten wir viele Foci.</p>
|
||||
<p>Was ist ein Applicative überhaupt? Eine schwächere Monade (nur 1x Anwendung und<br>
|
||||
kein Bind - dafür kann man die beliebig oft hintereinanderhängen).</p>
|
||||
<div class="sourceCode" id="cb31"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> <span class="dt">Functor</span> f <span class="ot">=></span> <span class="dt">Applicative</span> f <span class="kw">where</span></span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb31"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> <span class="dt">Functor</span> f <span class="ot">=></span> <span class="dt">Applicative</span> f <span class="kw">where</span></span>
|
||||
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a><span class="ot"> pure ::</span> a <span class="ot">-></span> f a</span>
|
||||
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a><span class="ot"> (<*>) ::</span> f (a <span class="ot">-></span> b) <span class="ot">-></span> f a <span class="ot">-></span> f b</span>
|
||||
<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb31-5"><a href="#cb31-5" aria-hidden="true" tabindex="-1"></a><span class="co">-- Monade als Applicative:</span></span>
|
||||
<span id="cb31-6"><a href="#cb31-6" aria-hidden="true" tabindex="-1"></a><span class="fu">pure</span> <span class="ot">=</span> <span class="fu">return</span></span>
|
||||
<span id="cb31-7"><a href="#cb31-7" aria-hidden="true" tabindex="-1"></a>mf <span class="op"><*></span> mx <span class="ot">=</span> <span class="kw">do</span> { f <span class="ot"><-</span> mf; x <span class="ot"><-</span> mx; <span class="fu">return</span> (f x) }</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb31-7"><a href="#cb31-7" aria-hidden="true" tabindex="-1"></a>mf <span class="op"><*></span> mx <span class="ot">=</span> <span class="kw">do</span> { f <span class="ot"><-</span> mf; x <span class="ot"><-</span> mx; <span class="fu">return</span> (f x) }</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Recap: Was macht eine Lens:</p>
|
||||
<div class="sourceCode" id="cb32"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Adress</span> <span class="ot">=</span> <span class="dt">A</span> {<span class="ot"> _road ::</span> <span class="dt">String</span></span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb32"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Adress</span> <span class="ot">=</span> <span class="dt">A</span> {<span class="ot"> _road ::</span> <span class="dt">String</span></span>
|
||||
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a> ,<span class="ot"> _city ::</span> <span class="dt">String</span></span>
|
||||
<span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a> ,<span class="ot"> _postcode ::</span> <span class="dt">String</span> }</span>
|
||||
<span id="cb32-4"><a href="#cb32-4" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb32-5"><a href="#cb32-5" aria-hidden="true" tabindex="-1"></a><span class="ot">road ::</span> <span class="dt">Lens'</span> <span class="dt">Adress</span> <span class="dt">String</span></span>
|
||||
<span id="cb32-6"><a href="#cb32-6" aria-hidden="true" tabindex="-1"></a>road elt_fn (<span class="dt">A</span> r c p) <span class="ot">=</span> (\r' <span class="ot">-></span> <span class="dt">A</span> r' c p) <span class="op"><$></span> (elt_fn r)</span>
|
||||
<span id="cb32-7"><a href="#cb32-7" aria-hidden="true" tabindex="-1"></a><span class="co">-- | "Hole" | | Thing to put in|</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb32-7"><a href="#cb32-7" aria-hidden="true" tabindex="-1"></a><span class="co">-- | "Hole" | | Thing to put in|</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Wenn man nun road & city gleichzeitig bearbeiten will:</p>
|
||||
<div class="sourceCode" id="cb33"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a><span class="ot">addr_strs ::</span> <span class="dt">Traversal'</span> <span class="dt">Address</span> <span class="dt">String</span></span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb33"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a><span class="ot">addr_strs ::</span> <span class="dt">Traversal'</span> <span class="dt">Address</span> <span class="dt">String</span></span>
|
||||
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a>addr_strs elt_fn (<span class="dt">A</span> r c p)</span>
|
||||
<span id="cb33-3"><a href="#cb33-3" aria-hidden="true" tabindex="-1"></a> <span class="ot">=</span> <span class="op">...</span> (\r' c' <span class="ot">-></span> <span class="dt">A</span> r' c' p) <span class="op">..</span> (elt_fn r) <span class="op">..</span> (elt_fn c) <span class="op">..</span></span>
|
||||
<span id="cb33-4"><a href="#cb33-4" aria-hidden="true" tabindex="-1"></a><span class="co">-- | function with 2 "Holes"| first Thing | second Thing</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb33-4"><a href="#cb33-4" aria-hidden="true" tabindex="-1"></a><span class="co">-- | function with 2 "Holes"| first Thing | second Thing</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>fmap kann nur 1 Loch stopfen, aber nicht mit n Löchern umgehen. Applicative mit<br>
|
||||
<*> kann das.<br>
|
||||
Somit gibt sich</p>
|
||||
<div class="sourceCode" id="cb34"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a><span class="ot">addr_strs ::</span> <span class="dt">Traversal'</span> <span class="dt">Address</span> <span class="dt">String</span></span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb34"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a><span class="ot">addr_strs ::</span> <span class="dt">Traversal'</span> <span class="dt">Address</span> <span class="dt">String</span></span>
|
||||
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a>addr_strs elt_fn (<span class="dt">A</span> r c p)</span>
|
||||
<span id="cb34-3"><a href="#cb34-3" aria-hidden="true" tabindex="-1"></a> <span class="ot">=</span> <span class="fu">pure</span> (\r' c' <span class="ot">-></span> <span class="dt">A</span> r' c' p) <span class="op"><*></span> (elt_fn r) <span class="op"><*></span> (elt_fn c)</span>
|
||||
<span id="cb34-4"><a href="#cb34-4" aria-hidden="true" tabindex="-1"></a><span class="co">-- lift in Appl. | function with 2 "Holes"| first Thing | second Thing</span></span>
|
||||
@ -1066,13 +1071,13 @@ Somit gibt sich</p>
|
||||
<span id="cb34-6"><a href="#cb34-6" aria-hidden="true" tabindex="-1"></a><span class="ot">addr_strs ::</span> <span class="dt">Traversal'</span> <span class="dt">Address</span> <span class="dt">String</span></span>
|
||||
<span id="cb34-7"><a href="#cb34-7" aria-hidden="true" tabindex="-1"></a>addr_strs elt_fn (<span class="dt">A</span> r c p)</span>
|
||||
<span id="cb34-8"><a href="#cb34-8" aria-hidden="true" tabindex="-1"></a> <span class="ot">=</span> (\r' c' <span class="ot">-></span> <span class="dt">A</span> r' c' p) <span class="op"><$></span> (elt_fn r) <span class="op"><*></span> (elt_fn c)</span>
|
||||
<span id="cb34-9"><a href="#cb34-9" aria-hidden="true" tabindex="-1"></a><span class="co">-- pure x <*> y == x <$> y</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb34-9"><a href="#cb34-9" aria-hidden="true" tabindex="-1"></a><span class="co">-- pure x <*> y == x <$> y</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Wie würd eine modify-funktion aussehen?</p>
|
||||
<div class="sourceCode" id="cb35"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a><span class="ot">over ::</span> <span class="dt">Lens'</span> s a <span class="ot">-></span> (a <span class="ot">-></span> a) <span class="ot">-></span> s <span class="ot">-></span> s</span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb35"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a><span class="ot">over ::</span> <span class="dt">Lens'</span> s a <span class="ot">-></span> (a <span class="ot">-></span> a) <span class="ot">-></span> s <span class="ot">-></span> s</span>
|
||||
<span id="cb35-2"><a href="#cb35-2" aria-hidden="true" tabindex="-1"></a>over ln f <span class="ot">=</span> runIdentity <span class="op">.</span> ln (<span class="dt">Identity</span> <span class="op">.</span> f)</span>
|
||||
<span id="cb35-3"><a href="#cb35-3" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb35-4"><a href="#cb35-4" aria-hidden="true" tabindex="-1"></a><span class="ot">over ::</span> <span class="dt">Traversal'</span> s a <span class="ot">-></span> (a <span class="ot">-></span> a) <span class="ot">-></span> s <span class="ot">-></span> s</span>
|
||||
<span id="cb35-5"><a href="#cb35-5" aria-hidden="true" tabindex="-1"></a>over ln f <span class="ot">=</span> runIdentity <span class="op">.</span> ln (<span class="dt">Identity</span> <span class="op">.</span> f)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb35-5"><a href="#cb35-5" aria-hidden="true" tabindex="-1"></a>over ln f <span class="ot">=</span> runIdentity <span class="op">.</span> ln (<span class="dt">Identity</span> <span class="op">.</span> f)</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Der Code ist derselbe - nur der Typ ist generischer. Auch die anderen Dinge<br>
|
||||
funktioniert diese Erweiterung (für Identity und Const muss man noch ein paar<br>
|
||||
dummy-Instanzen schreiben um sie von Functor auf Applicative oder Monad zu heben</p>
|
||||
@ -1097,22 +1102,22 @@ steuern. Beispisweise eine Function anwenden auf</p>
|
||||
<h2 class="anchored" data-anchor-id="wie-es-in-lens-wirklich-aussieht">Wie es in Lens wirklich aussieht</h2>
|
||||
<p>In diesem Artikel wurde nur auf Monomorphic Lenses eingegangen. In der richtigen<br>
|
||||
Library ist eine Lens</p>
|
||||
<div class="sourceCode" id="cb36"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb36-1"><a href="#cb36-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Lens'</span> s a <span class="ot">=</span> <span class="dt">Lens</span> s s a a</span>
|
||||
<span id="cb36-2"><a href="#cb36-2" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Lens</span> s t a b <span class="ot">=</span> <span class="kw">forall</span> f<span class="op">.</span> <span class="dt">Functor</span> f <span class="ot">=></span> (a <span class="ot">-></span> f b) <span class="ot">-></span> (s <span class="ot">-></span> f t)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb36"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb36-1"><a href="#cb36-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Lens'</span> s a <span class="ot">=</span> <span class="dt">Lens</span> s s a a</span>
|
||||
<span id="cb36-2"><a href="#cb36-2" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Lens</span> s t a b <span class="ot">=</span> <span class="kw">forall</span> f<span class="op">.</span> <span class="dt">Functor</span> f <span class="ot">=></span> (a <span class="ot">-></span> f b) <span class="ot">-></span> (s <span class="ot">-></span> f t)</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>sodass sich auch die Typen ändern können um z.B. automatisch einen Konvertierten<br>
|
||||
(sicheren) Typen aus einer unsicheren Datenstruktur zu geben.</p>
|
||||
<p>Die modify-Funktion over ist auch</p>
|
||||
<div class="sourceCode" id="cb37"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb37-1"><a href="#cb37-1" aria-hidden="true" tabindex="-1"></a><span class="op">></span><span class="ot"> over ::</span> <span class="dt">Profunctor</span> p <span class="ot">=></span> <span class="dt">Setting</span> p s t a b <span class="ot">-></span> p a b <span class="ot">-></span> s <span class="ot">-></span> t</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb37"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb37-1"><a href="#cb37-1" aria-hidden="true" tabindex="-1"></a><span class="op">></span><span class="ot"> over ::</span> <span class="dt">Profunctor</span> p <span class="ot">=></span> <span class="dt">Setting</span> p s t a b <span class="ot">-></span> p a b <span class="ot">-></span> s <span class="ot">-></span> t</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<blockquote class="blockquote">
|
||||
<p><em>Edward is deeply in thrall to abstractionitis</em> - Simon Peyton Jones</p>
|
||||
</blockquote>
|
||||
<p>Lens alleine definiert 39 newtypes, 34 data-types und 194 Typsynonyme…<br>
|
||||
Ausschnitt</p>
|
||||
<div class="sourceCode" id="cb38"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb38-1"><a href="#cb38-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- traverseOf :: Functor f => Iso s t a b -> (a -> f b) -> s -> f t</span></span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb38"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb38-1"><a href="#cb38-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- traverseOf :: Functor f => Iso s t a b -> (a -> f b) -> s -> f t</span></span>
|
||||
<span id="cb38-2"><a href="#cb38-2" aria-hidden="true" tabindex="-1"></a><span class="co">-- traverseOf :: Functor f => Lens s t a b -> (a -> f b) -> s -> f t</span></span>
|
||||
<span id="cb38-3"><a href="#cb38-3" aria-hidden="true" tabindex="-1"></a><span class="co">-- traverseOf :: Applicative f => Traversal s t a b -> (a -> f b) -> s -> f t</span></span>
|
||||
<span id="cb38-4"><a href="#cb38-4" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb38-5"><a href="#cb38-5" aria-hidden="true" tabindex="-1"></a><span class="ot">traverseOf ::</span> <span class="dt">Over</span> p f s t a b <span class="ot">-></span> p a (f b) <span class="ot">-></span> s <span class="ot">-></span> f t</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb38-5"><a href="#cb38-5" aria-hidden="true" tabindex="-1"></a><span class="ot">traverseOf ::</span> <span class="dt">Over</span> p f s t a b <span class="ot">-></span> p a (f b) <span class="ot">-></span> s <span class="ot">-></span> f t</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>dafuq?</p>
|
||||
|
||||
|
||||
@ -1133,7 +1138,7 @@ Ausschnitt</p>
|
||||
a.appendChild(i);
|
||||
window.document.body.appendChild(a);
|
||||
}
|
||||
window.setColorSchemeToggle(window.hasAlternateSentinel())
|
||||
setColorSchemeToggle(hasAlternateSentinel())
|
||||
const icon = "";
|
||||
const anchorJS = new window.AnchorJS();
|
||||
anchorJS.options = {
|
||||
|
53
dist/Coding/Haskell/Webapp-Example/Main.hs.html
vendored
53
dist/Coding/Haskell/Webapp-Example/Main.hs.html
vendored
@ -2,7 +2,7 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="generator" content="quarto-1.7.23">
|
||||
<meta name="generator" content="quarto-1.8.17">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||||
|
||||
@ -68,17 +68,19 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<meta name="quarto:offset" content="../../../">
|
||||
<script src="../../../site_libs/quarto-html/quarto.js" type="module"></script>
|
||||
<script src="../../../site_libs/quarto-html/tabsets/tabsets.js" type="module"></script>
|
||||
<script src="../../../site_libs/quarto-html/axe/axe-check.js" type="module"></script>
|
||||
<script src="../../../site_libs/quarto-html/popper.min.js"></script>
|
||||
<script src="../../../site_libs/quarto-html/tippy.umd.min.js"></script>
|
||||
<script src="../../../site_libs/quarto-html/anchor.min.js"></script>
|
||||
<link href="../../../site_libs/quarto-html/tippy.css" rel="stylesheet">
|
||||
<link href="../../../site_libs/quarto-html/quarto-syntax-highlighting-dark-2c84ecb840a13f4c7993f9e5648f0c14.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles">
|
||||
<link href="../../../site_libs/quarto-html/quarto-syntax-highlighting-6cf5824034cebd0380a5b9c74c43f006.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles">
|
||||
<link href="../../../site_libs/quarto-html/quarto-syntax-highlighting-ff1c8a91a872873ab9706226229f9e30.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles">
|
||||
<link href="../../../site_libs/quarto-html/quarto-syntax-highlighting-dark-04b38c9dba5d7c0f1fe2b621b39e7e62.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles">
|
||||
<link href="../../../site_libs/quarto-html/quarto-syntax-highlighting-ff1c8a91a872873ab9706226229f9e30.css" rel="stylesheet" class="quarto-color-scheme-extra" id="quarto-text-highlighting-styles">
|
||||
<script src="../../../site_libs/bootstrap/bootstrap.min.js"></script>
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-ec71cb1e120c0dd41819aca960e74e38.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-dark-716ed94a23403968eaa6fe981e0cbf91.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="dark">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-ec71cb1e120c0dd41819aca960e74e38.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme-extra" id="quarto-bootstrap" data-mode="light">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-9b56b6674ace31b1957ea5f5ef42286f.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-dark-3c8015a3c2181875b3e8a350495bd83c.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="dark">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-9b56b6674ace31b1957ea5f5ef42286f.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme-extra" id="quarto-bootstrap" data-mode="light">
|
||||
<script id="quarto-search-options" type="application/json">{
|
||||
"location": "navbar",
|
||||
"copy-button": false,
|
||||
@ -131,7 +133,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
toggleBodyColorMode(bsSheetEl);
|
||||
}
|
||||
}
|
||||
window.setColorSchemeToggle = (alternate) => {
|
||||
const setColorSchemeToggle = (alternate) => {
|
||||
const toggles = window.document.querySelectorAll('.quarto-color-scheme-toggle');
|
||||
for (let i=0; i < toggles.length; i++) {
|
||||
const toggle = toggles[i];
|
||||
@ -164,7 +166,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
}
|
||||
manageTransitions('#quarto-margin-sidebar .nav-link', true);
|
||||
// Switch the toggles
|
||||
window.setColorSchemeToggle(alternate)
|
||||
setColorSchemeToggle(alternate)
|
||||
// Hack to workaround the fact that safari doesn't
|
||||
// properly recolor the scrollbar when toggling (#1455)
|
||||
if (navigator.userAgent.indexOf('Safari') > 0 && navigator.userAgent.indexOf('Chrome') == -1) {
|
||||
@ -204,7 +206,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
const isFileUrl = () => {
|
||||
return window.location.protocol === 'file:';
|
||||
}
|
||||
window.hasAlternateSentinel = () => {
|
||||
const hasAlternateSentinel = () => {
|
||||
let styleSentinel = getColorSchemeSentinel();
|
||||
if (styleSentinel !== null) {
|
||||
return styleSentinel === "alternate";
|
||||
@ -232,7 +234,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
const baseTheme = document.querySelector('#giscus-base-theme')?.value ?? 'light';
|
||||
const alternateTheme = document.querySelector('#giscus-alt-theme')?.value ?? 'dark';
|
||||
let newTheme = '';
|
||||
if(darkModeDefault) {
|
||||
if(authorPrefersDark) {
|
||||
newTheme = isAlternate ? baseTheme : alternateTheme;
|
||||
} else {
|
||||
newTheme = isAlternate ? alternateTheme : baseTheme;
|
||||
@ -255,17 +257,20 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
changeGiscusTheme();
|
||||
}
|
||||
};
|
||||
const authorPrefersDark = false;
|
||||
const queryPrefersDark = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
const darkModeDefault = queryPrefersDark.matches;
|
||||
document.querySelector('link.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
|
||||
document.querySelector('link#quarto-text-highlighting-styles.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
|
||||
document.querySelector('link#quarto-bootstrap.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
|
||||
let localAlternateSentinel = darkModeDefault ? 'alternate' : 'default';
|
||||
// Dark / light mode switch
|
||||
window.quartoToggleColorScheme = () => {
|
||||
// Read the current dark / light value
|
||||
let toAlternate = !window.hasAlternateSentinel();
|
||||
let toAlternate = !hasAlternateSentinel();
|
||||
toggleColorMode(toAlternate);
|
||||
setStyleSentinel(toAlternate);
|
||||
toggleGiscusIfUsed(toAlternate, darkModeDefault);
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
};
|
||||
queryPrefersDark.addEventListener("change", e => {
|
||||
if(window.localStorage.getItem("quarto-color-scheme") !== null)
|
||||
@ -276,7 +281,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
toggleGiscusIfUsed(alternate, darkModeDefault);
|
||||
});
|
||||
// Switch to dark mode if need be
|
||||
if (window.hasAlternateSentinel()) {
|
||||
if (hasAlternateSentinel()) {
|
||||
toggleColorMode(true);
|
||||
} else {
|
||||
toggleColorMode(false);
|
||||
@ -288,6 +293,8 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<nav class="navbar navbar-expand-lg " data-bs-theme="dark">
|
||||
<div class="navbar-container container-fluid">
|
||||
<div class="navbar-brand-container mx-auto">
|
||||
<a href="../../../index.html" class="navbar-brand navbar-brand-logo">
|
||||
</a>
|
||||
<a class="navbar-brand" href="../../../index.html">
|
||||
<span class="navbar-title">Nicole Dresselhaus</span>
|
||||
</a>
|
||||
@ -299,12 +306,12 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<div class="collapse navbar-collapse" id="navbarCollapse">
|
||||
<ul class="navbar-nav navbar-nav-scroll me-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../../index.html"> <i class="bi bi-house" role="img">
|
||||
<a class="nav-link active" href="../../../index.html" aria-current="page"> <i class="bi bi-house" role="img">
|
||||
</i>
|
||||
<span class="menu-text">Home</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="../../../About/index.html" aria-current="page"> <i class="bi bi-file-person" role="img">
|
||||
<a class="nav-link" href="../../../About/index.html"> <i class="bi bi-file-person" role="img">
|
||||
</i>
|
||||
<span class="menu-text">About</span></a>
|
||||
</li>
|
||||
@ -342,6 +349,10 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-article page-navbar">
|
||||
<!-- sidebar -->
|
||||
<nav id="quarto-sidebar" class="sidebar collapse collapse-horizontal quarto-sidebar-collapse-item sidebar-navigation docked overflow-auto">
|
||||
<div class="pt-lg-2 mt-2 text-left sidebar-header">
|
||||
<a href="../../../index.html" class="sidebar-logo-link">
|
||||
</a>
|
||||
</div>
|
||||
<div class="sidebar-menu-container">
|
||||
<ul class="list-unstyled mt-1">
|
||||
<li class="sidebar-item sidebar-item-section">
|
||||
@ -385,12 +396,6 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<a href="../../../Writing/Obsidian-RAG.html" class="sidebar-item-text sidebar-link">
|
||||
<span class="menu-text">RAG für eine Obsidian-Wissensdatenbank: Technische Ansätze</span></a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="../../../Obsidian-Articles/Artikelbewertung durch LLM.html" class="sidebar-item-text sidebar-link">
|
||||
<span class="menu-text">Artikelbewertung durch ein Large Language Model (LLM) - Ein Beispiel aus der Praxis</span></a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
@ -651,7 +656,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
|
||||
|
||||
<p>Wie man das verwendet, siehe <a href="../../../Coding/Haskell/Webapp-Example/index.html">Webapp-Example</a>.</p>
|
||||
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# OPTIONS_GHC -Wno-name-shadowing #-}</span></span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# OPTIONS_GHC -Wno-name-shadowing #-}</span></span>
|
||||
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE FlexibleContexts #-}</span></span>
|
||||
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE LambdaCase #-}</span></span>
|
||||
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE OverloadedStrings #-}</span></span>
|
||||
@ -831,7 +836,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<span id="cb1-178"><a href="#cb1-178" aria-hidden="true" tabindex="-1"></a> out _ r status _ _ payload _</span>
|
||||
<span id="cb1-179"><a href="#cb1-179" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> statusCode status <span class="op"><</span> <span class="dv">300</span> <span class="ot">=</span> <span class="st">""</span></span>
|
||||
<span id="cb1-180"><a href="#cb1-180" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> statusCode status <span class="op">></span> <span class="dv">399</span> <span class="op">&&</span> statusCode status <span class="op"><</span> <span class="dv">500</span> <span class="ot">=</span> <span class="st">"Error code "</span><span class="op"><></span>toLogStr (statusCode status) <span class="op"><></span><span class="st">" sent. Request-Payload was: "</span><span class="op"><></span> <span class="fu">mconcat</span> (toLogStr <span class="op"><$></span> payload) <span class="op"><></span> <span class="st">"\n"</span></span>
|
||||
<span id="cb1-181"><a href="#cb1-181" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="fu">otherwise</span> <span class="ot">=</span> toLogStr (<span class="fu">show</span> r) <span class="op"><></span> <span class="st">"\n"</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb1-181"><a href="#cb1-181" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="fu">otherwise</span> <span class="ot">=</span> toLogStr (<span class="fu">show</span> r) <span class="op"><></span> <span class="st">"\n"</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
|
||||
|
||||
|
||||
@ -850,7 +855,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
a.appendChild(i);
|
||||
window.document.body.appendChild(a);
|
||||
}
|
||||
window.setColorSchemeToggle(window.hasAlternateSentinel())
|
||||
setColorSchemeToggle(hasAlternateSentinel())
|
||||
const icon = "";
|
||||
const anchorJS = new window.AnchorJS();
|
||||
anchorJS.options = {
|
||||
|
@ -2,7 +2,7 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="generator" content="quarto-1.7.23">
|
||||
<meta name="generator" content="quarto-1.8.17">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||||
|
||||
@ -68,17 +68,19 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<meta name="quarto:offset" content="../../../">
|
||||
<script src="../../../site_libs/quarto-html/quarto.js" type="module"></script>
|
||||
<script src="../../../site_libs/quarto-html/tabsets/tabsets.js" type="module"></script>
|
||||
<script src="../../../site_libs/quarto-html/axe/axe-check.js" type="module"></script>
|
||||
<script src="../../../site_libs/quarto-html/popper.min.js"></script>
|
||||
<script src="../../../site_libs/quarto-html/tippy.umd.min.js"></script>
|
||||
<script src="../../../site_libs/quarto-html/anchor.min.js"></script>
|
||||
<link href="../../../site_libs/quarto-html/tippy.css" rel="stylesheet">
|
||||
<link href="../../../site_libs/quarto-html/quarto-syntax-highlighting-dark-2c84ecb840a13f4c7993f9e5648f0c14.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles">
|
||||
<link href="../../../site_libs/quarto-html/quarto-syntax-highlighting-6cf5824034cebd0380a5b9c74c43f006.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles">
|
||||
<link href="../../../site_libs/quarto-html/quarto-syntax-highlighting-ff1c8a91a872873ab9706226229f9e30.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles">
|
||||
<link href="../../../site_libs/quarto-html/quarto-syntax-highlighting-dark-04b38c9dba5d7c0f1fe2b621b39e7e62.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles">
|
||||
<link href="../../../site_libs/quarto-html/quarto-syntax-highlighting-ff1c8a91a872873ab9706226229f9e30.css" rel="stylesheet" class="quarto-color-scheme-extra" id="quarto-text-highlighting-styles">
|
||||
<script src="../../../site_libs/bootstrap/bootstrap.min.js"></script>
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-ec71cb1e120c0dd41819aca960e74e38.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-dark-716ed94a23403968eaa6fe981e0cbf91.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="dark">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-ec71cb1e120c0dd41819aca960e74e38.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme-extra" id="quarto-bootstrap" data-mode="light">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-9b56b6674ace31b1957ea5f5ef42286f.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-dark-3c8015a3c2181875b3e8a350495bd83c.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="dark">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-9b56b6674ace31b1957ea5f5ef42286f.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme-extra" id="quarto-bootstrap" data-mode="light">
|
||||
<script id="quarto-search-options" type="application/json">{
|
||||
"location": "navbar",
|
||||
"copy-button": false,
|
||||
@ -131,7 +133,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
toggleBodyColorMode(bsSheetEl);
|
||||
}
|
||||
}
|
||||
window.setColorSchemeToggle = (alternate) => {
|
||||
const setColorSchemeToggle = (alternate) => {
|
||||
const toggles = window.document.querySelectorAll('.quarto-color-scheme-toggle');
|
||||
for (let i=0; i < toggles.length; i++) {
|
||||
const toggle = toggles[i];
|
||||
@ -164,7 +166,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
}
|
||||
manageTransitions('#quarto-margin-sidebar .nav-link', true);
|
||||
// Switch the toggles
|
||||
window.setColorSchemeToggle(alternate)
|
||||
setColorSchemeToggle(alternate)
|
||||
// Hack to workaround the fact that safari doesn't
|
||||
// properly recolor the scrollbar when toggling (#1455)
|
||||
if (navigator.userAgent.indexOf('Safari') > 0 && navigator.userAgent.indexOf('Chrome') == -1) {
|
||||
@ -204,7 +206,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
const isFileUrl = () => {
|
||||
return window.location.protocol === 'file:';
|
||||
}
|
||||
window.hasAlternateSentinel = () => {
|
||||
const hasAlternateSentinel = () => {
|
||||
let styleSentinel = getColorSchemeSentinel();
|
||||
if (styleSentinel !== null) {
|
||||
return styleSentinel === "alternate";
|
||||
@ -232,7 +234,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
const baseTheme = document.querySelector('#giscus-base-theme')?.value ?? 'light';
|
||||
const alternateTheme = document.querySelector('#giscus-alt-theme')?.value ?? 'dark';
|
||||
let newTheme = '';
|
||||
if(darkModeDefault) {
|
||||
if(authorPrefersDark) {
|
||||
newTheme = isAlternate ? baseTheme : alternateTheme;
|
||||
} else {
|
||||
newTheme = isAlternate ? alternateTheme : baseTheme;
|
||||
@ -255,17 +257,20 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
changeGiscusTheme();
|
||||
}
|
||||
};
|
||||
const authorPrefersDark = false;
|
||||
const queryPrefersDark = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
const darkModeDefault = queryPrefersDark.matches;
|
||||
document.querySelector('link.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
|
||||
document.querySelector('link#quarto-text-highlighting-styles.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
|
||||
document.querySelector('link#quarto-bootstrap.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
|
||||
let localAlternateSentinel = darkModeDefault ? 'alternate' : 'default';
|
||||
// Dark / light mode switch
|
||||
window.quartoToggleColorScheme = () => {
|
||||
// Read the current dark / light value
|
||||
let toAlternate = !window.hasAlternateSentinel();
|
||||
let toAlternate = !hasAlternateSentinel();
|
||||
toggleColorMode(toAlternate);
|
||||
setStyleSentinel(toAlternate);
|
||||
toggleGiscusIfUsed(toAlternate, darkModeDefault);
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
};
|
||||
queryPrefersDark.addEventListener("change", e => {
|
||||
if(window.localStorage.getItem("quarto-color-scheme") !== null)
|
||||
@ -276,7 +281,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
toggleGiscusIfUsed(alternate, darkModeDefault);
|
||||
});
|
||||
// Switch to dark mode if need be
|
||||
if (window.hasAlternateSentinel()) {
|
||||
if (hasAlternateSentinel()) {
|
||||
toggleColorMode(true);
|
||||
} else {
|
||||
toggleColorMode(false);
|
||||
@ -288,6 +293,8 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<nav class="navbar navbar-expand-lg " data-bs-theme="dark">
|
||||
<div class="navbar-container container-fluid">
|
||||
<div class="navbar-brand-container mx-auto">
|
||||
<a href="../../../index.html" class="navbar-brand navbar-brand-logo">
|
||||
</a>
|
||||
<a class="navbar-brand" href="../../../index.html">
|
||||
<span class="navbar-title">Nicole Dresselhaus</span>
|
||||
</a>
|
||||
@ -299,12 +306,12 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<div class="collapse navbar-collapse" id="navbarCollapse">
|
||||
<ul class="navbar-nav navbar-nav-scroll me-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../../index.html"> <i class="bi bi-house" role="img">
|
||||
<a class="nav-link active" href="../../../index.html" aria-current="page"> <i class="bi bi-house" role="img">
|
||||
</i>
|
||||
<span class="menu-text">Home</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="../../../About/index.html" aria-current="page"> <i class="bi bi-file-person" role="img">
|
||||
<a class="nav-link" href="../../../About/index.html"> <i class="bi bi-file-person" role="img">
|
||||
</i>
|
||||
<span class="menu-text">About</span></a>
|
||||
</li>
|
||||
@ -342,6 +349,10 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-article page-navbar">
|
||||
<!-- sidebar -->
|
||||
<nav id="quarto-sidebar" class="sidebar collapse collapse-horizontal quarto-sidebar-collapse-item sidebar-navigation docked overflow-auto">
|
||||
<div class="pt-lg-2 mt-2 text-left sidebar-header">
|
||||
<a href="../../../index.html" class="sidebar-logo-link">
|
||||
</a>
|
||||
</div>
|
||||
<div class="sidebar-menu-container">
|
||||
<ul class="list-unstyled mt-1">
|
||||
<li class="sidebar-item sidebar-item-section">
|
||||
@ -385,12 +396,6 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<a href="../../../Writing/Obsidian-RAG.html" class="sidebar-item-text sidebar-link">
|
||||
<span class="menu-text">RAG für eine Obsidian-Wissensdatenbank: Technische Ansätze</span></a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="../../../Obsidian-Articles/Artikelbewertung durch LLM.html" class="sidebar-item-text sidebar-link">
|
||||
<span class="menu-text">Artikelbewertung durch ein Large Language Model (LLM) - Ein Beispiel aus der Praxis</span></a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
@ -651,7 +656,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
|
||||
|
||||
<p>Anleitung siehe <a href="../../../Coding/Haskell/Webapp-Example/index.html">Webapp-Example</a>.</p>
|
||||
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# OPTIONS_GHC -Wno-orphans #-}</span></span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# OPTIONS_GHC -Wno-orphans #-}</span></span>
|
||||
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# OPTIONS_GHC -Wno-name-shadowing #-}</span></span>
|
||||
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE DeriveAnyClass #-}</span></span>
|
||||
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE DeriveFunctor #-}</span></span>
|
||||
@ -727,7 +732,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<span id="cb1-74"><a href="#cb1-74" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb1-75"><a href="#cb1-75" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb1-76"><a href="#cb1-76" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Out</span> <span class="dt">Response</span></span>
|
||||
<span id="cb1-77"><a href="#cb1-77" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">FromBSON</span> <span class="dt">Repsonse</span> <span class="co">-- FromBSON-Instanz geht immer davon aus, dass alle keys da sind (ggf. mit null bei Nothing).</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb1-77"><a href="#cb1-77" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">FromBSON</span> <span class="dt">Repsonse</span> <span class="co">-- FromBSON-Instanz geht immer davon aus, dass alle keys da sind (ggf. mit null bei Nothing).</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
|
||||
|
||||
|
||||
@ -746,7 +751,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
a.appendChild(i);
|
||||
window.document.body.appendChild(a);
|
||||
}
|
||||
window.setColorSchemeToggle(window.hasAlternateSentinel())
|
||||
setColorSchemeToggle(hasAlternateSentinel())
|
||||
const icon = "";
|
||||
const anchorJS = new window.AnchorJS();
|
||||
anchorJS.options = {
|
||||
|
87
dist/Coding/Haskell/Webapp-Example/index.html
vendored
87
dist/Coding/Haskell/Webapp-Example/index.html
vendored
@ -2,7 +2,7 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="generator" content="quarto-1.7.23">
|
||||
<meta name="generator" content="quarto-1.8.17">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||||
|
||||
@ -68,17 +68,19 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<meta name="quarto:offset" content="../../../">
|
||||
<script src="../../../site_libs/quarto-html/quarto.js" type="module"></script>
|
||||
<script src="../../../site_libs/quarto-html/tabsets/tabsets.js" type="module"></script>
|
||||
<script src="../../../site_libs/quarto-html/axe/axe-check.js" type="module"></script>
|
||||
<script src="../../../site_libs/quarto-html/popper.min.js"></script>
|
||||
<script src="../../../site_libs/quarto-html/tippy.umd.min.js"></script>
|
||||
<script src="../../../site_libs/quarto-html/anchor.min.js"></script>
|
||||
<link href="../../../site_libs/quarto-html/tippy.css" rel="stylesheet">
|
||||
<link href="../../../site_libs/quarto-html/quarto-syntax-highlighting-dark-2c84ecb840a13f4c7993f9e5648f0c14.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles">
|
||||
<link href="../../../site_libs/quarto-html/quarto-syntax-highlighting-6cf5824034cebd0380a5b9c74c43f006.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles">
|
||||
<link href="../../../site_libs/quarto-html/quarto-syntax-highlighting-ff1c8a91a872873ab9706226229f9e30.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles">
|
||||
<link href="../../../site_libs/quarto-html/quarto-syntax-highlighting-dark-04b38c9dba5d7c0f1fe2b621b39e7e62.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles">
|
||||
<link href="../../../site_libs/quarto-html/quarto-syntax-highlighting-ff1c8a91a872873ab9706226229f9e30.css" rel="stylesheet" class="quarto-color-scheme-extra" id="quarto-text-highlighting-styles">
|
||||
<script src="../../../site_libs/bootstrap/bootstrap.min.js"></script>
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-ec71cb1e120c0dd41819aca960e74e38.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-dark-716ed94a23403968eaa6fe981e0cbf91.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="dark">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-ec71cb1e120c0dd41819aca960e74e38.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme-extra" id="quarto-bootstrap" data-mode="light">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-9b56b6674ace31b1957ea5f5ef42286f.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-dark-3c8015a3c2181875b3e8a350495bd83c.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="dark">
|
||||
<link href="../../../site_libs/bootstrap/bootstrap-9b56b6674ace31b1957ea5f5ef42286f.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme-extra" id="quarto-bootstrap" data-mode="light">
|
||||
<script id="quarto-search-options" type="application/json">{
|
||||
"location": "navbar",
|
||||
"copy-button": false,
|
||||
@ -131,7 +133,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
toggleBodyColorMode(bsSheetEl);
|
||||
}
|
||||
}
|
||||
window.setColorSchemeToggle = (alternate) => {
|
||||
const setColorSchemeToggle = (alternate) => {
|
||||
const toggles = window.document.querySelectorAll('.quarto-color-scheme-toggle');
|
||||
for (let i=0; i < toggles.length; i++) {
|
||||
const toggle = toggles[i];
|
||||
@ -164,7 +166,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
}
|
||||
manageTransitions('#quarto-margin-sidebar .nav-link', true);
|
||||
// Switch the toggles
|
||||
window.setColorSchemeToggle(alternate)
|
||||
setColorSchemeToggle(alternate)
|
||||
// Hack to workaround the fact that safari doesn't
|
||||
// properly recolor the scrollbar when toggling (#1455)
|
||||
if (navigator.userAgent.indexOf('Safari') > 0 && navigator.userAgent.indexOf('Chrome') == -1) {
|
||||
@ -204,7 +206,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
const isFileUrl = () => {
|
||||
return window.location.protocol === 'file:';
|
||||
}
|
||||
window.hasAlternateSentinel = () => {
|
||||
const hasAlternateSentinel = () => {
|
||||
let styleSentinel = getColorSchemeSentinel();
|
||||
if (styleSentinel !== null) {
|
||||
return styleSentinel === "alternate";
|
||||
@ -232,7 +234,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
const baseTheme = document.querySelector('#giscus-base-theme')?.value ?? 'light';
|
||||
const alternateTheme = document.querySelector('#giscus-alt-theme')?.value ?? 'dark';
|
||||
let newTheme = '';
|
||||
if(darkModeDefault) {
|
||||
if(authorPrefersDark) {
|
||||
newTheme = isAlternate ? baseTheme : alternateTheme;
|
||||
} else {
|
||||
newTheme = isAlternate ? alternateTheme : baseTheme;
|
||||
@ -255,17 +257,20 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
changeGiscusTheme();
|
||||
}
|
||||
};
|
||||
const authorPrefersDark = false;
|
||||
const queryPrefersDark = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
const darkModeDefault = queryPrefersDark.matches;
|
||||
document.querySelector('link.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
|
||||
document.querySelector('link#quarto-text-highlighting-styles.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
|
||||
document.querySelector('link#quarto-bootstrap.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
|
||||
let localAlternateSentinel = darkModeDefault ? 'alternate' : 'default';
|
||||
// Dark / light mode switch
|
||||
window.quartoToggleColorScheme = () => {
|
||||
// Read the current dark / light value
|
||||
let toAlternate = !window.hasAlternateSentinel();
|
||||
let toAlternate = !hasAlternateSentinel();
|
||||
toggleColorMode(toAlternate);
|
||||
setStyleSentinel(toAlternate);
|
||||
toggleGiscusIfUsed(toAlternate, darkModeDefault);
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
};
|
||||
queryPrefersDark.addEventListener("change", e => {
|
||||
if(window.localStorage.getItem("quarto-color-scheme") !== null)
|
||||
@ -276,7 +281,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
toggleGiscusIfUsed(alternate, darkModeDefault);
|
||||
});
|
||||
// Switch to dark mode if need be
|
||||
if (window.hasAlternateSentinel()) {
|
||||
if (hasAlternateSentinel()) {
|
||||
toggleColorMode(true);
|
||||
} else {
|
||||
toggleColorMode(false);
|
||||
@ -288,6 +293,8 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<nav class="navbar navbar-expand-lg " data-bs-theme="dark">
|
||||
<div class="navbar-container container-fluid">
|
||||
<div class="navbar-brand-container mx-auto">
|
||||
<a href="../../../index.html" class="navbar-brand navbar-brand-logo">
|
||||
</a>
|
||||
<a class="navbar-brand" href="../../../index.html">
|
||||
<span class="navbar-title">Nicole Dresselhaus</span>
|
||||
</a>
|
||||
@ -299,12 +306,12 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<div class="collapse navbar-collapse" id="navbarCollapse">
|
||||
<ul class="navbar-nav navbar-nav-scroll me-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../../index.html"> <i class="bi bi-house" role="img">
|
||||
<a class="nav-link active" href="../../../index.html" aria-current="page"> <i class="bi bi-house" role="img">
|
||||
</i>
|
||||
<span class="menu-text">Home</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="../../../About/index.html" aria-current="page"> <i class="bi bi-file-person" role="img">
|
||||
<a class="nav-link" href="../../../About/index.html"> <i class="bi bi-file-person" role="img">
|
||||
</i>
|
||||
<span class="menu-text">About</span></a>
|
||||
</li>
|
||||
@ -342,6 +349,10 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-article page-navbar">
|
||||
<!-- sidebar -->
|
||||
<nav id="quarto-sidebar" class="sidebar collapse collapse-horizontal quarto-sidebar-collapse-item sidebar-navigation docked overflow-auto">
|
||||
<div class="pt-lg-2 mt-2 text-left sidebar-header">
|
||||
<a href="../../../index.html" class="sidebar-logo-link">
|
||||
</a>
|
||||
</div>
|
||||
<div class="sidebar-menu-container">
|
||||
<ul class="list-unstyled mt-1">
|
||||
<li class="sidebar-item sidebar-item-section">
|
||||
@ -385,12 +396,6 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<a href="../../../Writing/Obsidian-RAG.html" class="sidebar-item-text sidebar-link">
|
||||
<span class="menu-text">RAG für eine Obsidian-Wissensdatenbank: Technische Ansätze</span></a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="../../../Obsidian-Articles/Artikelbewertung durch LLM.html" class="sidebar-item-text sidebar-link">
|
||||
<span class="menu-text">Artikelbewertung durch ein Large Language Model (LLM) - Ein Beispiel aus der Praxis</span></a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
@ -687,18 +692,18 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<section id="erstellen-eines-neuen-projektes" class="level3">
|
||||
<h3 class="anchored" data-anchor-id="erstellen-eines-neuen-projektes">Erstellen eines neuen Projektes</h3>
|
||||
<p>Zunächst erstellen wir in normales Haskell-Projekt ohne Funktionalität & Firlefanz:</p>
|
||||
<div class="sourceCode" id="cb1"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ex">stack</span> new myservice</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ex">stack</span> new myservice</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Dies erstellt ein neues Verzeichnis und das generelle scaffolding. Nach einer kurzen Anpassung der <code>stack.yaml</code> (resolver auf unserer setzen; aktuell: <code>lts-17.4</code>) fügen wir am Ende der Datei</p>
|
||||
<div class="sourceCode" id="cb2"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="fu">allow-newer</span><span class="kw">:</span><span class="at"> </span><span class="ch">true</span></span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="fu">allow-newer</span><span class="kw">:</span><span class="at"> </span><span class="ch">true</span></span>
|
||||
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="fu">ghc-options</span><span class="kw">:</span></span>
|
||||
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="at"> </span><span class="fu">"$locals"</span><span class="kw">:</span><span class="at"> -fwrite-ide-info</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="at"> </span><span class="fu">"$locals"</span><span class="kw">:</span><span class="at"> -fwrite-ide-info</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>ein. Anschließend organisieren™ wir uns noch eine gute <code>.gitignore</code> und initialisieren das git mittels <code>git init; git add .; git commit -m "initial scaffold"</code></p>
|
||||
</section>
|
||||
<section id="generierung-der-api" class="level3">
|
||||
<h3 class="anchored" data-anchor-id="generierung-der-api">Generierung der API</h3>
|
||||
<p>Da die API immer wieder neu generiert werden kann (und sollte!) liegt sich in einem unterverzeichnis des Hauptprojektes.</p>
|
||||
<p>Initial ist es das einfachste ein leeres temporäres Verzeichnis woanders zu erstellen, die <code>api-doc.yml</code> hinein kopieren und folgendes ausführen:</p>
|
||||
<div class="sourceCode" id="cb3"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ex">openapi-generator</span> generate <span class="at">-g</span> haskell <span class="at">-o</span> . <span class="at">-i</span> api-doc.yml</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ex">openapi-generator</span> generate <span class="at">-g</span> haskell <span class="at">-o</span> . <span class="at">-i</span> api-doc.yml</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Dieses erstellt einem dann eine komplette library inkl. Datentypen. Wichtig: Der Name in der <code>api-doc</code> sollte vom Namen des Services (oben <code>myservice</code>) abweichen - entweder in Casing oder im Namen direkt. Suffixe wie API schneidet der Generator hier leider ab. (Wieso das ganze? Es entstehen nachher 2 libraries, <code>foo</code> & <code>fooAPI</code>. Da der generator das API abschneidet endet man mit foo & foo und der compiler meckert, dass er nicht weiß, welche lib gemeint ist).</p>
|
||||
<p>danach: wie gewohnt <code>git init; git add .; git commit -m "initial"</code>. Auf dem Server der Wahl (github, gitea, gitlab, …) nun ein Repository erstellen (am Besten: <code>myserviceAPI</code> - nach Konvention ist alles auf API endend autogeneriert!) und den Anweisungen nach ein remote hinzufügen & pushen.</p>
|
||||
<section id="wieder-zurück-im-haskell-service" class="level4">
|
||||
@ -706,32 +711,32 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<p>In unserem eigentlichen Service müssen wir nun die API einbinden. Dazu erstellen wir ein Verzeichnis <code>libs</code> (Konvention) und machen ein <code>git submodule add <repository-url> libs/myserviceAPI</code></p>
|
||||
<p>Git hat nun die API in das submodul gepackt und wir können das oben erstellte temporäre Verzeichnis wieder löschen.</p>
|
||||
<p>Anschließend müssen wir stack noch erklären, dass wir die API da nun liegen haben und passen wieder die <code>stack.yaml</code> an, indem wir das Verzeichnis unter packages hinzufügen.</p>
|
||||
<div class="sourceCode" id="cb4"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="fu">packages</span><span class="kw">:</span></span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="fu">packages</span><span class="kw">:</span></span>
|
||||
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="at"> </span><span class="kw">-</span><span class="at"> .</span></span>
|
||||
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="at"> </span><span class="kw">-</span><span class="at"> libs/myserviceAPI</span><span class="co"> # <<</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="at"> </span><span class="kw">-</span><span class="at"> libs/myserviceAPI</span><span class="co"> # <<</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Nun können wir in der <code>package.yaml</code> (oder <code>myservice.cabal</code>, falls kein <code>hpack</code> verwendet wird) unter den dependencies unsere API hinzufügen (name wie die cabal-Datei in <code>libs/myserviceAPI</code>).</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="einbinden-anderer-microservices" class="level3">
|
||||
<h3 class="anchored" data-anchor-id="einbinden-anderer-microservices">Einbinden anderer Microservices</h3>
|
||||
<p>Funktioniert komplett analog zu dem vorgehen oben (ohne das generieren natürlich :grin:). <code>stack.yaml</code> editieren und zu den packages hinzufügen:</p>
|
||||
<div class="sourceCode" id="cb5"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="fu">packages</span><span class="kw">:</span></span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="fu">packages</span><span class="kw">:</span></span>
|
||||
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="at"> </span><span class="kw">-</span><span class="at"> .</span></span>
|
||||
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="at"> </span><span class="kw">-</span><span class="at"> libs/myserviceAPI</span></span>
|
||||
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="at"> </span><span class="kw">-</span><span class="at"> libs/myCoolMLServiceAPI</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="at"> </span><span class="kw">-</span><span class="at"> libs/myCoolMLServiceAPI</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>in der <code>package.yaml</code> (oder der cabal) die dependencies hinzufügen und schon haben wir die Features zur Verfügung und können gegen diese Services reden.</p>
|
||||
</section>
|
||||
<section id="entfernen-von-anderen-technologienmicroservices" class="level3">
|
||||
<h3 class="anchored" data-anchor-id="entfernen-von-anderen-technologienmicroservices">Entfernen von anderen Technologien/Microservices</h3>
|
||||
<p>In git ist das entfernen von Submodules etwas frickelig, daher hier ein copy&paste der <a href="https://gist.github.com/myusuf3/7f645819ded92bda6677">GitHub-Antwort</a>:</p>
|
||||
<div class="sourceCode" id="cb6"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="co">## Remove the submodule entry from .git/config</span></span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="co">## Remove the submodule entry from .git/config</span></span>
|
||||
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="fu">git</span> submodule deinit <span class="at">-f</span> path/to/submodule</span>
|
||||
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="co">## Remove the submodule directory from the superproject's .git/modules directory</span></span>
|
||||
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="ex">rm-rf</span> .git/modules/path/to/submodule</span>
|
||||
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a><span class="co">## Remove the entry in .gitmodules and remove the submodule directory located at path/to/submodule</span></span>
|
||||
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a><span class="fu">git</span> rm-f path/to/submodule</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a><span class="fu">git</span> rm-f path/to/submodule</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Falls das nicht klappt, gibt es alternative Vorschläge unter dem Link oben.</p>
|
||||
</section>
|
||||
<section id="woher-weiss-ich-was-wo-liegt-dokumentation-halloo" class="level3">
|
||||
@ -743,9 +748,9 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<li><code>...../index.html</code> - hier sind nur die direkten dependencies aufgeführt.</li>
|
||||
</ul>
|
||||
<p>Wenn man einen lokalen Webserver startet kann man mittels “s” auch die interaktive Suche öffnen (Suche nach Typen, Funktionen, Signaturen, etc.). In Bash mit <code>python3</code> geht das z.b. einfach über:</p>
|
||||
<div class="sourceCode" id="cb7"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="bu">cd</span> <span class="va">$(</span><span class="ex">stack</span> path <span class="at">--local-doc-root</span><span class="va">)</span></span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="bu">cd</span> <span class="va">$(</span><span class="ex">stack</span> path <span class="at">--local-doc-root</span><span class="va">)</span></span>
|
||||
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="ex">python3</span> <span class="at">-m</span> SimpleHTTPServer 8000</span>
|
||||
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="ex">firefox</span> <span class="st">"http://localhost:8000"</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="ex">firefox</span> <span class="st">"http://localhost:8000"</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
</section>
|
||||
<section id="implementation-des-services-und-start" class="level3">
|
||||
<h3 class="anchored" data-anchor-id="implementation-des-services-und-start">Implementation des Services und Start</h3>
|
||||
@ -759,7 +764,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
</ul>
|
||||
<p>Für die Main kann man prinzipiell eine Main andere Services copy/pasten. Im folgenden eine Annotierte main-Funktion - zu den einzelnen Voraussetzungen kommen wir im Anschluss.</p>
|
||||
<p></p><p></p><details><summary>Main.hs anzeigen</summary><blockquote class="blockquote"><p></p>
|
||||
<div class="sourceCode" id="cb8" data-code-fold="true" data-code-summary="Code anzeigen"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# OPTIONS_GHC -Wno-name-shadowing #-}</span></span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" data-code-fold="true" data-code-summary="Code anzeigen"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# OPTIONS_GHC -Wno-name-shadowing #-}</span></span>
|
||||
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE FlexibleContexts #-}</span></span>
|
||||
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE LambdaCase #-}</span></span>
|
||||
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE OverloadedStrings #-}</span></span>
|
||||
@ -939,7 +944,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<span id="cb8-178"><a href="#cb8-178" aria-hidden="true" tabindex="-1"></a> out _ r status _ _ payload _</span>
|
||||
<span id="cb8-179"><a href="#cb8-179" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> statusCode status <span class="op"><</span> <span class="dv">300</span> <span class="ot">=</span> <span class="st">""</span></span>
|
||||
<span id="cb8-180"><a href="#cb8-180" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> statusCode status <span class="op">></span> <span class="dv">399</span> <span class="op">&&</span> statusCode status <span class="op"><</span> <span class="dv">500</span> <span class="ot">=</span> <span class="st">"Error code "</span><span class="op"><></span>toLogStr (statusCode status) <span class="op"><></span><span class="st">" sent. Request-Payload was: "</span><span class="op"><></span> <span class="fu">mconcat</span> (toLogStr <span class="op"><$></span> payload) <span class="op"><></span> <span class="st">"\n"</span></span>
|
||||
<span id="cb8-181"><a href="#cb8-181" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="fu">otherwise</span> <span class="ot">=</span> toLogStr (<span class="fu">show</span> r) <span class="op"><></span> <span class="st">"\n"</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb8-181"><a href="#cb8-181" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="fu">otherwise</span> <span class="ot">=</span> toLogStr (<span class="fu">show</span> r) <span class="op"><></span> <span class="st">"\n"</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
</blockquote></details></section>
|
||||
<section id="weitere-instanzen-und-definitionen-die-der-generator-noch-nicht-macht" class="level4">
|
||||
<h4 class="anchored" data-anchor-id="weitere-instanzen-und-definitionen-die-der-generator-noch-nicht-macht">Weitere Instanzen und Definitionen, die der Generator (noch) nicht macht</h4>
|
||||
@ -969,7 +974,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
</ul></li>
|
||||
</ul>
|
||||
<p></p><p></p><details><summary>Types.hs anzeigen</summary><blockquote class="blockquote"><p></p>
|
||||
<div class="sourceCode" id="cb9"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# OPTIONS_GHC -Wno-orphans #-}</span></span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb9"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# OPTIONS_GHC -Wno-orphans #-}</span></span>
|
||||
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# OPTIONS_GHC -Wno-name-shadowing #-}</span></span>
|
||||
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE DeriveAnyClass #-}</span></span>
|
||||
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE DeriveFunctor #-}</span></span>
|
||||
@ -1045,12 +1050,12 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<span id="cb9-74"><a href="#cb9-74" aria-hidden="true" tabindex="-1"></a> </span>
|
||||
<span id="cb9-75"><a href="#cb9-75" aria-hidden="true" tabindex="-1"></a> </span>
|
||||
<span id="cb9-76"><a href="#cb9-76" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Out</span> <span class="dt">Response</span></span>
|
||||
<span id="cb9-77"><a href="#cb9-77" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">FromBSON</span> <span class="dt">Repsonse</span> <span class="co">-- FromBSON-Instanz geht immer davon aus, dass alle keys da sind (ggf. mit null bei Nothing).</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb9-77"><a href="#cb9-77" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">FromBSON</span> <span class="dt">Repsonse</span> <span class="co">-- FromBSON-Instanz geht immer davon aus, dass alle keys da sind (ggf. mit null bei Nothing).</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
</blockquote></details></section>
|
||||
<section id="was-noch-zu-tun-ist" class="level4">
|
||||
<h4 class="anchored" data-anchor-id="was-noch-zu-tun-ist">Was noch zu tun ist</h4>
|
||||
<p>Den Service implementieren. Einfach ein neues Modul aufmachen (z.B. <code>MyService.Handler</code> oder <code>MyService.DieserEndpunktbereich</code>/<code>MyService.JenerEndpunktbereich</code>) und dort die Funktion implementieren, die man in der <code>Main.hs</code> benutzt hat. In dem Handler habt ihr dann keinen Stress mehr mit Validierung, networking, logging, etc. pp. weil alles in der Main abgehandelt wurde und ihr nur noch den “Happy-Case” implementieren müsst. Beispiel für unseren Handler oben:</p>
|
||||
<div class="sourceCode" id="cb10"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ot">myApiEndpointV1Post ::</span> <span class="dt">MonadIO</span> m <span class="ot">=></span> <span class="dt">ServerConfig</span> <span class="ot">-></span> (<span class="dt">ClientEnv</span>,<span class="dt">ClientEnv</span>) <span class="ot">-></span> <span class="dt">TQueue</span> <span class="dt">BS.ByteString</span> <span class="ot">-></span> ([<span class="dt">LogItem</span>] <span class="ot">-></span> <span class="dt">IO</span> ()) <span class="ot">-></span> <span class="dt">Request</span> <span class="ot">-></span> m <span class="dt">Response</span></span>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb10"><pre class="sourceCode haskell code-with-copy"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ot">myApiEndpointV1Post ::</span> <span class="dt">MonadIO</span> m <span class="ot">=></span> <span class="dt">ServerConfig</span> <span class="ot">-></span> (<span class="dt">ClientEnv</span>,<span class="dt">ClientEnv</span>) <span class="ot">-></span> <span class="dt">TQueue</span> <span class="dt">BS.ByteString</span> <span class="ot">-></span> ([<span class="dt">LogItem</span>] <span class="ot">-></span> <span class="dt">IO</span> ()) <span class="ot">-></span> <span class="dt">Request</span> <span class="ot">-></span> m <span class="dt">Response</span></span>
|
||||
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>myApiEndpointV1Post sc calls amqPost <span class="fu">log</span> req <span class="ot">=</span> <span class="kw">do</span></span>
|
||||
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a> liftIO <span class="op">.</span> <span class="fu">log</span> <span class="op">$</span> [<span class="dt">Info</span> <span class="op">$</span> <span class="st">"recieved "</span><span class="op"><></span>pretty req] <span class="co">-- input-logging</span></span>
|
||||
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a> liftIO <span class="op">.</span> atomically <span class="op">.</span> writeTQueue <span class="op">.</span> LBS.toStrict <span class="op">$</span> <span class="st">"{\"hey Kibana, i recieved:\""</span> <span class="op"><></span> A.encode (pretty req) <span class="op"><></span> <span class="st">"}"</span> <span class="co">-- log in activeMQ/Kibana</span></span>
|
||||
@ -1064,7 +1069,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a> liftIO <span class="op">.</span> access pipe master <span class="st">"DatabaseName"</span> <span class="op">$</span> <span class="kw">do</span></span>
|
||||
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a> ifM (auth (myServiceMongoUsername sc) (myServiceMongoPassword sc)) (<span class="fu">return</span> ()) (liftIO <span class="op">.</span> printLog <span class="op">.</span> <span class="fu">pure</span> <span class="op">.</span> <span class="dt">Error</span> <span class="op">$</span> <span class="st">"MongoDB: Login failed."</span>)</span>
|
||||
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true" tabindex="-1"></a> save <span class="st">"DatabaseCollection"</span> [<span class="st">"_id"</span> <span class="op">=:</span> <span class="dv">1337</span>, <span class="st">"entry"</span> <span class="op">=:</span> ret] <span class="co">-- selbe id wie oben ;)</span></span>
|
||||
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true" tabindex="-1"></a> <span class="fu">return</span> ret</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true" tabindex="-1"></a> <span class="fu">return</span> ret</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Diese dummy-Antwort führt auf, wie gut man die ganzen Sachen mischen kann.</p>
|
||||
<ul>
|
||||
<li>Logging in die Dateien/<code>stdout</code> - je nach Konfiguration</li>
|
||||
@ -1085,7 +1090,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
</section>
|
||||
<section id="wie-sorge-ich-für-bessere-warnungen-damit-der-compiler-meine-bugs-fängt" class="level5">
|
||||
<h5 class="anchored" data-anchor-id="wie-sorge-ich-für-bessere-warnungen-damit-der-compiler-meine-bugs-fängt">Wie sorge ich für bessere Warnungen, damit der Compiler meine Bugs fängt?</h5>
|
||||
<div class="sourceCode" id="cb11"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="ex">stack</span> build <span class="at">--file-watch</span> <span class="at">--ghc-options</span> <span class="st">'-freverse-errors -W -Wall -Wcompat'</span> <span class="at">--interleaved-output</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb11"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="ex">stack</span> build <span class="at">--file-watch</span> <span class="at">--ghc-options</span> <span class="st">'-freverse-errors -W -Wall -Wcompat'</span> <span class="at">--interleaved-output</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
|
||||
<p>Was tut das?</p>
|
||||
<ul>
|
||||
<li><code>--file-watch</code>: automatisches (minimales) kompilieren bei dateiänderungen</li>
|
||||
@ -1153,7 +1158,7 @@ pre > code.sourceCode > span > a:first-child::before { text-decoration: underlin
|
||||
a.appendChild(i);
|
||||
window.document.body.appendChild(a);
|
||||
}
|
||||
window.setColorSchemeToggle(window.hasAlternateSentinel())
|
||||
setColorSchemeToggle(hasAlternateSentinel())
|
||||
const icon = "";
|
||||
const anchorJS = new window.AnchorJS();
|
||||
anchorJS.options = {
|
||||
|
Reference in New Issue
Block a user