Add (untranslated) Japanese and Dutch pages for code notes.
This commit is contained in:
parent
dacb75e1ad
commit
3f51764997
41
portfolio/pages/jp/software/code/blazor/commands.md
Normal file
41
portfolio/pages/jp/software/code/blazor/commands.md
Normal file
@ -0,0 +1,41 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "Blazor commands"
|
||||
code: "Blazor"
|
||||
---
|
||||
|
||||
A collection of commands useful to work with blazor web applications.
|
||||
|
||||
|
||||
* Create a new application.
|
||||
|
||||
`dotnet new blazor -o BlazorWebAppMovies`
|
||||
|
||||
* Compile and run the application, and hot-reload upon changes.
|
||||
|
||||
`dotnet watch`
|
||||
|
||||
* VS Code build:
|
||||
|
||||
Command Palette (Ctrl+Shift+P), use the `.NET: Build` command to build the app.
|
||||
|
||||
* Create gitignore file:
|
||||
|
||||
`dotnet new gitignore`
|
||||
|
||||
* [Scaffolding example](https://learn.microsoft.com/en-us/aspnet/core/blazor/tutorials/movie-database-app/part-2?view=aspnetcore-8.0&pivots=vsc#scaffold-the-model):
|
||||
|
||||
`dotnet aspnet-codegenerator blazor CRUD -dbProvider sqlite -dc BlazorWebAppMovies.Data.BlazorWebAppMoviesContext -m Movie -outDir Components/Pages`
|
||||
|
||||
|
||||
### Entity framework
|
||||
|
||||
* Create a migration, this is also used when creating a new migration when the model has changed.
|
||||
|
||||
`dotnet ef migrations add InitialCreate`
|
||||
|
||||
* Update the database:
|
||||
|
||||
`dotnet ef database update`
|
||||
|
||||
49
portfolio/pages/jp/software/code/csharp/strings.md
Normal file
49
portfolio/pages/jp/software/code/csharp/strings.md
Normal file
@ -0,0 +1,49 @@
|
||||
## Strings
|
||||
|
||||
#### Verbatim string with @:
|
||||
|
||||
Preserves whitespace and characters like '\' do not need to be escaped.
|
||||
|
||||
```c#
|
||||
Console.WriteLine(@" c:\source\repos
|
||||
(this is where your code goes)");
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
> c:\source\repos
|
||||
> (this is where your code goes)
|
||||
```
|
||||
|
||||
#### Escaped Unicode
|
||||
|
||||
Use the **\u** plus a four-character code to represent Unicode characters (UTF-16) in a string.
|
||||
|
||||
[Japanese UTF-16 table](http://www.rikai.com/library/kanjitables/kanji_codes.unicode.shtml)
|
||||
|
||||
```c#
|
||||
Console.WriteLine("\u3053\u3093\u306B\u3061\u306F World!");
|
||||
```
|
||||
|
||||
Output (UTF-16):
|
||||
```
|
||||
> こんにちは World!
|
||||
```
|
||||
|
||||
```c#
|
||||
// To generate Japanese invoices:
|
||||
Console.Write("\n\n\u65e5\u672c\u8a9e\u306e\u8acb\u6c42\u66f8\u3092\u751f\u6210\u3059\u308b\u306b\u306f\uff1a");
|
||||
```
|
||||
|
||||
Output (UTF-16):
|
||||
```
|
||||
> 日本語の請求書を生成するには:
|
||||
```
|
||||
|
||||
#### String interpolation
|
||||
|
||||
Can be combined with verbatim strings.
|
||||
|
||||
```c#
|
||||
Console.WriteLine($@"C:\Output\{projectName}\Data");
|
||||
```
|
||||
10
portfolio/pages/jp/software/code/csharp/types.md
Normal file
10
portfolio/pages/jp/software/code/csharp/types.md
Normal file
@ -0,0 +1,10 @@
|
||||
## Types
|
||||
|
||||
Float Type Precision
|
||||
|
||||
float ~6-9 digits 0.25F
|
||||
double ~15-17 digits 0.25
|
||||
decimal 28-29 digits 0.25M
|
||||
|
||||
Both lowercase 'f' or 'F' can be used, same for 'm' and 'M'.
|
||||
|
||||
8
portfolio/pages/jp/software/code/elm/composition.md
Normal file
8
portfolio/pages/jp/software/code/elm/composition.md
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "Composition"
|
||||
code: "Elm"
|
||||
---
|
||||
|
||||
[Elm composition operators << and >>](https://package.elm-lang.org/packages/elm/core/latest/Basics#(%3C%3C))
|
||||
59
portfolio/pages/jp/software/code/elm/dry.md
Normal file
59
portfolio/pages/jp/software/code/elm/dry.md
Normal file
@ -0,0 +1,59 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "DRY"
|
||||
code: "Elm"
|
||||
---
|
||||
|
||||
DRY means: "[Don't Repeat Yourself](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)".
|
||||
|
||||
This page contains some common mistakes I make when writing Elm code and how I processed feedback afterwards to improve it.
|
||||
|
||||
|
||||
```elm
|
||||
let
|
||||
render item =
|
||||
case warning item of
|
||||
Just (Error tooltip) ->
|
||||
[ Html.text <| text item
|
||||
, Html.i
|
||||
[ HtmlAttributes.class "icon-error"
|
||||
, HtmlAttributes.title tooltip
|
||||
]
|
||||
]
|
||||
-- Another case, very similar to the one above.
|
||||
Just (Warning tooltip) ->
|
||||
[ Html.text <| text item
|
||||
, Html.i
|
||||
[ HtmlAttributes.class "icon-warning"
|
||||
, HtmlAttributes.title <| getWarningTooltip tooltip
|
||||
]
|
||||
]
|
||||
|
||||
Nothing ->
|
||||
[ Html.text <| text item ]
|
||||
|
||||
```
|
||||
|
||||
```elm
|
||||
let
|
||||
render item =
|
||||
let
|
||||
createHtml class tooltip =
|
||||
[ Html.text <| text item
|
||||
, Html.i
|
||||
[ HtmlAttributes.class class
|
||||
, HtmlAttributes.title tooltip
|
||||
]
|
||||
]
|
||||
in
|
||||
case warning item of
|
||||
Just (Error tooltip) ->
|
||||
createHtml "icon-error" tooltip
|
||||
|
||||
Just (Warning tooltip) ->
|
||||
createHtml "icon-warning" (getWarningTooltip tooltip)
|
||||
|
||||
Nothing ->
|
||||
[ Html.text <| text item ]
|
||||
```
|
||||
33
portfolio/pages/jp/software/code/elm/formatting.md
Normal file
33
portfolio/pages/jp/software/code/elm/formatting.md
Normal file
@ -0,0 +1,33 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "Formatting"
|
||||
code: "Elm"
|
||||
---
|
||||
|
||||
You can add a docstring to an elm function like this:
|
||||
|
||||
```elm
|
||||
|
||||
|
||||
{- Render the Elm icon. -}
|
||||
|
||||
|
||||
elmIcon : E.Element msg
|
||||
elmIcon =
|
||||
|
||||
```
|
||||
|
||||
But upon formatting, 2 new lines are automatically added.
|
||||
|
||||
By adding a "|" pipe character, the docstring will get appended to the top op the function header.
|
||||
|
||||
```elm
|
||||
|
||||
|
||||
{-| Render the Elm icon.
|
||||
-}
|
||||
elmIcon : E.Element msg
|
||||
elmIcon =
|
||||
|
||||
```
|
||||
93
portfolio/pages/jp/software/code/elm/maybeandthen.md
Normal file
93
portfolio/pages/jp/software/code/elm/maybeandthen.md
Normal file
@ -0,0 +1,93 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "Maybe AndThen"
|
||||
code: "Elm"
|
||||
---
|
||||
|
||||
Given are these functions, **hasPrecedingReleasedVersions** and **getSelectedItemIndex**, need to be optimized.
|
||||
|
||||
|
||||
```elm
|
||||
|
||||
hasPrecedingReleasedVersions =
|
||||
case getSelectedItemIndex data.versionData of
|
||||
Just index ->
|
||||
Array.slice 0 index data.versionData.allItems
|
||||
|> Array.toList
|
||||
|> List.any
|
||||
(\item ->
|
||||
case item of
|
||||
ReleasedVersion _ ->
|
||||
True
|
||||
_ ->
|
||||
False
|
||||
)
|
||||
Nothing ->
|
||||
False
|
||||
```
|
||||
|
||||
Currently, **getSelectedItemIndex** is defined as such:
|
||||
|
||||
```elm
|
||||
|
||||
getSelectedItemIndex : Model id -> Maybe Int
|
||||
getSelectedItemIndex model =
|
||||
case getSelectedItem model of
|
||||
Just selected ->
|
||||
Array.toIndexedList model.allItems
|
||||
|> List.filter (\( _, item ) -> item == selected)
|
||||
|> List.head
|
||||
|> Maybe.map Tuple.first
|
||||
|
||||
Nothing ->
|
||||
Nothing
|
||||
|
||||
|
||||
```
|
||||
|
||||
But using [Maybe.andThen](https://package.elm-lang.org/packages/elm/core/latest/Maybe#andThen) will allow to get rid of the **Nothing -> Nothing** here.
|
||||
Also the **List.filter** and **List.head** combination can be shortened with a **List.find**.
|
||||
|
||||
```elm
|
||||
|
||||
getSelectedItemIndex : Model id -> Maybe Int
|
||||
getSelectedItemIndex model =
|
||||
getSelectedItem model
|
||||
|> Maybe.andThen
|
||||
(\selected ->
|
||||
Array.toIndexedList model.allItems
|
||||
|> List.find (\( _, item ) -> item == selected)
|
||||
|> Maybe.map Tuple.first
|
||||
)
|
||||
|
||||
|
||||
```
|
||||
|
||||
Finally, define a custom funcion to determine the boolean:
|
||||
|
||||
```elm
|
||||
|
||||
itemIsReleased : VersionData id -> Bool
|
||||
itemIsReleased versionData =
|
||||
case versionData of
|
||||
WorkingVersion _ ->
|
||||
False
|
||||
ReleasedVersion
|
||||
True
|
||||
|
||||
```
|
||||
|
||||
The original function can now be changed to:
|
||||
|
||||
```elm
|
||||
|
||||
hasPrecedingReleasedVersions =
|
||||
case getSelectedItemIndex data.versionData of
|
||||
Just index ->
|
||||
Array.slice 0 index data.versionData.allItems
|
||||
|> Array.toList
|
||||
|> List.any itemIsReleased
|
||||
Nothing ->
|
||||
False
|
||||
```
|
||||
50
portfolio/pages/jp/software/code/elm/maybemap.md
Normal file
50
portfolio/pages/jp/software/code/elm/maybemap.md
Normal file
@ -0,0 +1,50 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "Maybe Map"
|
||||
code: "Elm"
|
||||
---
|
||||
|
||||
Here, a tooltip title attribute needs to be added if it is **Just**.
|
||||
|
||||
```elm
|
||||
let
|
||||
divAttributes =
|
||||
[ HA.classList
|
||||
[ ( "my-div", True ) ]
|
||||
]
|
||||
|
||||
combinedAttributes =
|
||||
case settings.tooltip of
|
||||
Just tooltip ->
|
||||
divAttributes ++ [ HA.title tooltip ]
|
||||
|
||||
Nothing ->
|
||||
divAttributes
|
||||
in
|
||||
H.div
|
||||
combinedAttributes
|
||||
[ content ]
|
||||
|
||||
```
|
||||
|
||||
This can be easier written with the [Maybe.map](https://package.elm-lang.org/packages/elm/core/latest/Maybe#map) and [Maybe.withDefault](https://package.elm-lang.org/packages/elm/core/latest/Maybe#withDefault) functions.
|
||||
|
||||
```elm
|
||||
|
||||
let
|
||||
divAttributes =
|
||||
[ HA.classList
|
||||
[ ( "my-div", True ) ]
|
||||
]
|
||||
|
||||
tooltipAttribute =
|
||||
Maybe.map (\tooltip -> [ HA.title tooltip ]) settings.tooltip |> Maybe.withDefault []
|
||||
-- or you can do:
|
||||
settings.tooltip |> Maybe.map (\tooltip -> [ HA.title tooltip ]) |> Maybe.withDefault []
|
||||
|
||||
in
|
||||
H.div
|
||||
(divAttributes ++ tooltipAttribute)
|
||||
[ content ]
|
||||
```
|
||||
36
portfolio/pages/jp/software/code/haskell/caesar-cipher.md
Normal file
36
portfolio/pages/jp/software/code/haskell/caesar-cipher.md
Normal file
@ -0,0 +1,36 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "Caesar Cipher"
|
||||
code: "Haskell"
|
||||
---
|
||||
|
||||
The implementation of the [Caesar's Cipher](https://en.wikipedia.org/wiki/Caesar_cipher) in Haskell.
|
||||
|
||||
*Source*: [Programming in Haskell, by Graham Hutton](https://people.cs.nott.ac.uk/pszgmh/pih.html)
|
||||
|
||||
```haskell
|
||||
import Data.Char
|
||||
import Prelude
|
||||
|
||||
let2int :: Char -> Int
|
||||
let2int c | isLower c = ord c - ord 'a'
|
||||
| otherwise = ord c - ord 'A'
|
||||
|
||||
int2let :: Int -> Bool -> Char
|
||||
int2let n isLowercase = chr (ord (if isLowercase then 'a' else 'A') + n)
|
||||
|
||||
shift :: Int -> Char -> Char
|
||||
shift n c | isLower c = int2let ((let2int c + n) `mod` 26) (isLower c)
|
||||
| isUpper c = int2let ((let2int c + n) `mod` 26) (isLower c)
|
||||
| otherwise = c
|
||||
|
||||
encode :: Int -> String -> String
|
||||
encode n xs = [shift n x | x <- xs]
|
||||
|
||||
|
||||
ghci> encode 5 "This is a Caesar Cipher"
|
||||
-- "Ymnx nx f Hfjxfw Hnumjw"
|
||||
ghci> encode (-5) "Ymnx nx f Hfjxfw Hnumjw"
|
||||
-- "This is a Caesar Cipher"
|
||||
```
|
||||
@ -0,0 +1,44 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "Conditional expressions and Guarded equations"
|
||||
code: "Haskell"
|
||||
---
|
||||
|
||||
### Conditional expressions
|
||||
|
||||
```haskell
|
||||
signum :: Int -> Int
|
||||
signum n = if n < 0 then -1 else
|
||||
if n == 0 then 0 else 1
|
||||
```
|
||||
|
||||
And a **safetail** function, where an empty list is returned instead of an error when given an empty list.
|
||||
|
||||
```haskell
|
||||
safetail :: [a] -> [a]
|
||||
safetail xs = if length xs > 0 then tail xs else []
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Guarded equations
|
||||
|
||||
An alternative to conditional expressions, functions can be defined with guarded equations.
|
||||
|
||||
An example of the **signum** function:
|
||||
|
||||
```haskell
|
||||
signum :: Int -> Int
|
||||
signum n | n < 0 = -1
|
||||
| n == 0 = 0
|
||||
| otherwise = 1
|
||||
```
|
||||
|
||||
Here is **safetail** with guarded equations:
|
||||
|
||||
```haskell
|
||||
safetail :: [a] -> [a]
|
||||
safetail xs | length xs > 0 = tail xs
|
||||
| otherwise = []
|
||||
```
|
||||
@ -0,0 +1,71 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "Curried functions"
|
||||
code: "Haskell"
|
||||
---
|
||||
|
||||
A function can return another function.
|
||||
|
||||
```haskell
|
||||
add' :: Int -> (Int -> Int)
|
||||
add' x y = x+y
|
||||
```
|
||||
|
||||
Here, **add'** is a function that takes an **Int** for an argument and results in a function of type: **Int -> Int**.
|
||||
The function definition takes an integer **x**, followed by an integer **y**, it can be [curried](https://en.wikipedia.org/wiki/Currying).
|
||||
|
||||
```haskell
|
||||
addThree = add' 3 -- This is now a function with type: Int -> Int
|
||||
result = addThree 5 -- Evaluates to 8
|
||||
```
|
||||
|
||||
Another example,
|
||||
|
||||
```haskell
|
||||
mult :: Int -> (Int -> (Int -> Int))
|
||||
mult x y z = x*y*z
|
||||
```
|
||||
|
||||
And is applied as following:
|
||||
|
||||
```haskell
|
||||
mult x y z
|
||||
-- Means same as:
|
||||
((mult x) y) z
|
||||
```
|
||||
|
||||
When used, it is like:
|
||||
|
||||
```haskell
|
||||
multTwo = mult 2 -- This is now a function with type: Int -> (Int -> Int)
|
||||
multTwoThree = multTwo 3 -- This is: Int -> Int
|
||||
result = multTwoThree 4 -- Evaluates to 2 * 3 * 4 = 24
|
||||
|
||||
-- or just:
|
||||
|
||||
result = mult 2 3 4 -- Also evaluates to 24
|
||||
```
|
||||
|
||||
**Partial application** is about using curried functions, applying only some arguments and getting back a new function.
|
||||
|
||||
```haskell
|
||||
double = mult 2 -- This is now a function with type: Int -> (Int -> Int)
|
||||
|
||||
result = double 3 4 -- Evaluates to 2 * 3 * 4 = 24
|
||||
|
||||
quadruple = double 2 -- Now quadruple :: Int -> Int
|
||||
result = quadruple 3 -- Evaluates to 2 * 2 * 3 = 12
|
||||
```
|
||||
|
||||
The arrow function **->** in Haskell types is assumed to associate from the right.
|
||||
|
||||
```haskell
|
||||
Int -> Int -> Int -> Int
|
||||
|
||||
-- is:
|
||||
|
||||
Int -> (Int -> (Int -> Int))
|
||||
```
|
||||
|
||||
So, unless tuples are required, all functions in Haskell with multiple arguments are actually defined as curried functions, with a way to reduce excessive parenthesis.
|
||||
@ -0,0 +1,257 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "Programming in Haskell by Graham Hutton"
|
||||
code: "Haskell"
|
||||
---
|
||||
|
||||
This book is what I used to learn the programming language Haskell. This page contains all my exercise answers.
|
||||
|
||||
*Source*: [Programming in Haskell, by Graham Hutton](https://people.cs.nott.ac.uk/pszgmh/pih.html)
|
||||
|
||||
* [Chapter 4 - Defining functions](#Chapter-4)
|
||||
* [Chapter 5 - List comprehensions](#Chapter-5)
|
||||
* [Chapter 6 - Recursive functions](#Chapter-6)
|
||||
|
||||
---
|
||||
|
||||
#### Chapter-4
|
||||
##### Defining functions
|
||||
|
||||
###### exercise 1
|
||||
|
||||
```haskell
|
||||
halve :: [Int] -> ([Int], [Int])
|
||||
halve xs =
|
||||
(take n xs, drop n xs)
|
||||
where n = length xs `div` 2
|
||||
|
||||
halve :: [Int] -> ([Int], [Int])
|
||||
halve xs =
|
||||
splitAt (length xs `div` 2) xs
|
||||
```
|
||||
|
||||
###### exercise 2
|
||||
|
||||
```haskell
|
||||
-- a (head & tail)
|
||||
third :: [a] -> a
|
||||
third xs = head (tail (tail xs))
|
||||
|
||||
-- b (list indexing)
|
||||
third :: [a] -> a
|
||||
third xs = xs !! 2
|
||||
|
||||
-- c (pattern matching)
|
||||
third :: [a] -> a
|
||||
third (_:_:a:_) = a
|
||||
```
|
||||
|
||||
###### exercise 3
|
||||
|
||||
```haskell
|
||||
-- a (conditional expression)
|
||||
safetail :: [a] -> [a]
|
||||
safetail xs = if length xs > 0 then tail xs else []
|
||||
|
||||
-- b (guarded equation)
|
||||
safetail :: [a] -> [a]
|
||||
safetail xs | length xs > 0 = tail xs
|
||||
| otherwise = []
|
||||
|
||||
-- c (pattern matching)
|
||||
safetail :: [a] -> [a]
|
||||
safetail [] = []
|
||||
safetail xs = tail xs
|
||||
-- or:
|
||||
-- safetail (_:xs) = xs
|
||||
```
|
||||
|
||||
###### exercise 4
|
||||
|
||||
```haskell
|
||||
(||) :: Bool -> Bool -> Bool
|
||||
True || _ = True
|
||||
_ || True = True
|
||||
_ = False
|
||||
```
|
||||
|
||||
###### exercise 5
|
||||
|
||||
```haskell
|
||||
-- Use conditional expressions to define &&.
|
||||
(<#>) :: Bool -> Bool -> Bool
|
||||
a <#> b =
|
||||
if a then
|
||||
if b then True else False
|
||||
else
|
||||
False
|
||||
```
|
||||
|
||||
###### exercise 6
|
||||
|
||||
```haskell
|
||||
(<#>) :: Bool -> Bool -> Bool
|
||||
a <#> b =
|
||||
if a then b else False
|
||||
```
|
||||
|
||||
###### exercise 7
|
||||
|
||||
```haskell
|
||||
mult :: Int -> Int -> Int -> Int
|
||||
mult x y z = x*y*z
|
||||
|
||||
-- rewritten to use lambda functions.
|
||||
mult :: Int -> (Int -> (Int -> Int))
|
||||
mult = \x -> (\y -> (\z -> x * y * z))
|
||||
```
|
||||
|
||||
###### exercise 8
|
||||
|
||||
[Luhn algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm)
|
||||
|
||||
```haskell
|
||||
luhnDouble :: Int -> Int
|
||||
luhnDouble x = x * 2 `mod` 9
|
||||
|
||||
luhn :: Int -> Int -> Int -> Int -> Bool
|
||||
luhn a b c d =
|
||||
sum ((map luhnDouble [a,c]) ++ [b,d]) `mod` 10 == 0
|
||||
|
||||
--ghci> luhn 1 7 8 4
|
||||
--True
|
||||
--ghci> luhn 4 7 8 3
|
||||
--False
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### Chapter-5
|
||||
##### List comprehensions
|
||||
|
||||
* exercise 1
|
||||
|
||||
```haskell
|
||||
sum [x^2 | x <- [0..100]]
|
||||
-- 338350
|
||||
```
|
||||
|
||||
###### exercise 2
|
||||
|
||||
```haskell
|
||||
grid :: Int -> Int -> [(Int, Int)]
|
||||
grid n m =
|
||||
[(x,y) | x <- [0..n], y <- [0..m]]
|
||||
|
||||
ghci> grid 1 2
|
||||
-- [(0,0),(0,1),(0,2),(1,0),(1,1),(1,2)]
|
||||
```
|
||||
|
||||
###### exercise 3
|
||||
|
||||
```haskell
|
||||
square :: Int -> [(Int,Int)]
|
||||
square n =
|
||||
[(x,y) | (x,y) <- grid n n, x /= y]
|
||||
|
||||
ghci> square 2
|
||||
-- [(0,1),(0,2),(1,0),(1,2),(2,0),(2,1)]
|
||||
```
|
||||
|
||||
###### exercise 4
|
||||
|
||||
```haskell
|
||||
replicate :: Int -> a -> [a]
|
||||
replicate n item =
|
||||
[item | _ <- [1..n]]
|
||||
|
||||
ghci> replicate 4 "test"
|
||||
-- ["test","test","test","test"]
|
||||
```
|
||||
|
||||
###### exercise 5
|
||||
|
||||
[Pythagorean theorem](https://en.wikipedia.org/wiki/Pythagorean_theorem)
|
||||
|
||||
```haskell
|
||||
isPythagorean :: Int -> Int -> Int -> Bool
|
||||
isPythagorean x y z =
|
||||
x^2 + y^2 == z^2
|
||||
|
||||
pyths :: Int -> [(Int,Int,Int)]
|
||||
pyths n =
|
||||
[(x,y,z) | x <- [1..n], y <- [1..n], z <- [1..n], isPythagorean x y z]
|
||||
|
||||
ghci> pyths 10
|
||||
-- [(3,4,5),(4,3,5),(6,8,10),(8,6,10)]
|
||||
```
|
||||
|
||||
###### exercise 6
|
||||
|
||||
[Perfect number](https://en.wikipedia.org/wiki/Perfect_number)
|
||||
|
||||
```haskell
|
||||
factors :: Int -> [Int]
|
||||
factors n = [x | x <- [1..n], n `mod` x == 0]
|
||||
|
||||
perfects :: Int -> [Int]
|
||||
perfects limit =
|
||||
[x | x <- [1..limit], sum (factors x) - x == x]
|
||||
|
||||
ghci> perfects 10000
|
||||
-- [6,28,496,8128]
|
||||
```
|
||||
|
||||
###### exercise 7
|
||||
*(I did not understand this one)*
|
||||
|
||||
###### exercise 8
|
||||
|
||||
Use the **find** library function in [Data.List 9.8.2](https://downloads.haskell.org/ghc/9.8.2/docs/libraries/base-4.19.1.0-179c/Data-List.html#v:find)
|
||||
|
||||
```haskell
|
||||
find :: (a -> Bool) -> [a] -> Maybe a
|
||||
-- The find function takes a predicate and a list and returns the first element in the list matching the predicate, or Nothing if there is no such element.
|
||||
```
|
||||
|
||||
```haskell
|
||||
positions :: Eq a => a -> [a] -> [Int]
|
||||
positions x xs =
|
||||
[i | (x',i) <- zip xs [0..], x == x']
|
||||
|
||||
-- using find function, though I doubt its correct...
|
||||
|
||||
positions :: Eq a => a -> [a] -> [Int]
|
||||
positions x xs =
|
||||
[i | (x',i) <- zip xs [0..], isJust (find (==x) [x'])]
|
||||
|
||||
positions 2 [1,1,0,2,46,6,8,9,2,3,4,2,4,9,2]
|
||||
-- [3,8,11,14]
|
||||
|
||||
-- You can also use:
|
||||
positions :: Eq a => a -> [a] -> [Int]
|
||||
positions x = elemIndices x
|
||||
```
|
||||
|
||||
###### exercise 9
|
||||
|
||||
[Scalar product](https://en.wikipedia.org/wiki/Dot_product)
|
||||
|
||||
```haskell
|
||||
scalarproduct :: [Int] -> [Int] -> Int
|
||||
scalarproduct xs ys =
|
||||
sum [x*y | (x,y) <- zip xs ys]
|
||||
|
||||
ghci> scalarproduct [1,2,3] [4,5,6]
|
||||
-- 32
|
||||
```
|
||||
|
||||
###### execise 10
|
||||
|
||||
[Caesar's Cipher](./caesar-cipher)
|
||||
|
||||
---
|
||||
|
||||
#### Chapter-6
|
||||
##### Recursive functions
|
||||
@ -0,0 +1,52 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "Lambda expressions"
|
||||
code: "Haskell"
|
||||
---
|
||||
|
||||
You can define a function like:
|
||||
|
||||
```haskell
|
||||
double :: Int -> Int
|
||||
double x = x + x
|
||||
```
|
||||
|
||||
Which can also be written as an anonymous function:
|
||||
|
||||
```haskell
|
||||
\x -> x + x
|
||||
```
|
||||
|
||||
Here, the **\\** symbol represents the Greek letter lambda: **λ**. This is derived from [lambda calculus](https://en.wikipedia.org/wiki/Lambda_calculus).
|
||||
|
||||
Lambda expressions can be used to more explicitly state that a function is returned.
|
||||
|
||||
Consider:
|
||||
|
||||
```haskell
|
||||
const :: a -> b -> a
|
||||
const x _ = x
|
||||
```
|
||||
|
||||
This can be written using a lambda expression and added parenthesis in the type definition. This is more explicit in that a function is being returned.
|
||||
|
||||
```haskell
|
||||
const :: a -> (b -> a)
|
||||
const x = \_ -> x
|
||||
```
|
||||
|
||||
And as an anonymous function. Consider the difference between these similar functions that return a list of odd numbers:
|
||||
|
||||
```haskell
|
||||
odds :: Int -> [Int]
|
||||
odds n = map f [0..n-1]
|
||||
where f x = x*2 + 1
|
||||
|
||||
odds :: Int -> [Int]
|
||||
odds n = map (\x -> x*2 + 1) [0..n-1]
|
||||
|
||||
-- > odds 15
|
||||
-- > [1,3,5,7,9,11,13,15,17,19,21,23,25,27,29]
|
||||
```
|
||||
|
||||
124
portfolio/pages/jp/software/code/haskell/lists.md
Normal file
124
portfolio/pages/jp/software/code/haskell/lists.md
Normal file
@ -0,0 +1,124 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "Lists"
|
||||
code: "Haskell"
|
||||
---
|
||||
|
||||
Lists are constructed one element at a time starting from an empty **[]** list using the *cons* operator **:**. For example, **[1,2,3]** can be decomposed as:
|
||||
|
||||
```haskell
|
||||
[1,2,3]
|
||||
--
|
||||
1 : [2,3]
|
||||
--
|
||||
1 : (2 : [3])
|
||||
--
|
||||
1 : (2 : (3 : []))
|
||||
```
|
||||
|
||||
To verify if a list with 3 numbers starts with the integer **1**, you can use pattern matching.
|
||||
|
||||
```haskell
|
||||
startsWithOne :: [Int] -> Bool
|
||||
startsWithOne [1, _, _] = True
|
||||
startsWithOne _ = False
|
||||
```
|
||||
|
||||
### Access elements
|
||||
|
||||
To access an element in a list, the indexing operator **!!** can be used.
|
||||
|
||||
```haskell
|
||||
-- Get the third element of a list.
|
||||
third :: [a] -> a
|
||||
third xs = xs !! 2
|
||||
```
|
||||
|
||||
### list comprehension
|
||||
|
||||
* Wikipedia: [List comprehension](https://en.wikipedia.org/wiki/List_comprehension).
|
||||
|
||||
|
||||
```haskell
|
||||
ghci> [x^2 | x <- [1..6]]
|
||||
-- [1,4,9,16,25,36]
|
||||
```
|
||||
|
||||
* The **|** symbol is read as: "*such that*".
|
||||
* The **<-** symbol is read as: "*drawn from*".
|
||||
* And **x <- [1..6]** is called a: "*generator*".
|
||||
|
||||
A list comprehension can have more than one generator.
|
||||
|
||||
```haskell
|
||||
ghci> [(x,y) | x <- [1,2,3], y <- [4,5]]
|
||||
-- [(1,4),(1,5),(2,4),(2,5),(3,4),(3,5)]
|
||||
```
|
||||
|
||||
Examples of list comprehensions:
|
||||
|
||||
```haskell
|
||||
halve :: [Int] -> ([Int], [Int])
|
||||
halve xs =
|
||||
([x | x <- xs, x < 4], [x | x <- xs, x >= 4])
|
||||
|
||||
-- halve [1,2,3,4,5,6]
|
||||
-- ([1,2,3],[4,5,6])
|
||||
```
|
||||
|
||||
How to actually halve the list properly:
|
||||
|
||||
```haskell
|
||||
halve :: [Int] -> ([Int], [Int])
|
||||
halve xs =
|
||||
(take n xs, drop n xs)
|
||||
where n = length xs `div` 2
|
||||
-- or
|
||||
splitAt (length xs `div` 2) xs
|
||||
```
|
||||
|
||||
Here the **length** function replaces all elements with a 1 and sums the total:
|
||||
|
||||
```haskell
|
||||
length :: [a] -> Int
|
||||
length xs = sum [1 | _ <- xs]
|
||||
length [1,4,8,90]
|
||||
-- 4
|
||||
```
|
||||
|
||||
You can use logical expressions as a **guard**, to filter values created by list comprehensions.
|
||||
|
||||
```haskell
|
||||
factors :: Int -> [Int]
|
||||
factors n = [x | x <- [1..n], n `mod` x == 0]
|
||||
|
||||
factors 20
|
||||
-- [1,2,4,5,10,20]
|
||||
factors 13
|
||||
-- [1,13]
|
||||
```
|
||||
|
||||
And you can use this **factors** function to determine **prime** numbers.
|
||||
|
||||
* Wikipedia: [Prime number](https://en.wikipedia.org/wiki/Prime_number)
|
||||
|
||||
```haskell
|
||||
prime :: Int -> Bool
|
||||
prime n = factors n == [1,n]
|
||||
|
||||
prime 15
|
||||
--False
|
||||
prime 13
|
||||
-- True
|
||||
```
|
||||
And with this **prime** function, we can use list comprehension to determine a range of prime numbers!
|
||||
|
||||
```haskell
|
||||
primes :: Int -> [Int]
|
||||
primes n = [x | x <- [2..n], prime x]
|
||||
|
||||
primes 50
|
||||
-- [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47]
|
||||
```
|
||||
|
||||
14
portfolio/pages/jp/software/code/haskell/pattern-matching.md
Normal file
14
portfolio/pages/jp/software/code/haskell/pattern-matching.md
Normal file
@ -0,0 +1,14 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "Pattern matching"
|
||||
code: "Haskell"
|
||||
---
|
||||
|
||||
An example to determine the third element of a list, (with at least 3 elements):
|
||||
|
||||
```haskell
|
||||
third :: [a] -> a
|
||||
third (_:_:x:_) = x
|
||||
```
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "Recursive functions"
|
||||
code: "Haskell"
|
||||
---
|
||||
|
||||
Recursion is the basic mechanism for looping in Haskell.
|
||||
|
||||
Determine the [factorial](https://en.wikipedia.org/wiki/Factorial).
|
||||
|
||||
```haskell
|
||||
factorial :: Int -> Int
|
||||
factorial 0 = 1
|
||||
factorial n = n * factorial (n-1)
|
||||
```
|
||||
|
||||
The factorial of 3, actually is calculated as such:
|
||||
|
||||
```haskell
|
||||
factorial 3
|
||||
3 * factorial 2
|
||||
3 * (2 * factorial 1)
|
||||
3 * (2 * (1 * factorial 0))
|
||||
3 * (2 * (1 * 1))
|
||||
```
|
||||
|
||||
38
portfolio/pages/jp/software/code/haskell/strings.md
Normal file
38
portfolio/pages/jp/software/code/haskell/strings.md
Normal file
@ -0,0 +1,38 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "Strings"
|
||||
code: "Haskell"
|
||||
---
|
||||
|
||||
Strings are not primitive types, but a list of characters.
|
||||
|
||||
For example,
|
||||
|
||||
```haskell
|
||||
"abc" :: String
|
||||
-- is actually:
|
||||
['a','b','c'] :: [Char]
|
||||
```
|
||||
Because of this, polymorphic functions on lists, can be used with strings.
|
||||
|
||||
```haskell
|
||||
"abcde" !! 2
|
||||
-- 'c'
|
||||
take 3 "abcde"
|
||||
-- "abc"
|
||||
length "abcde"
|
||||
-- 5
|
||||
zip "abc" [1,2,3,4]
|
||||
-- [('a',1),('b',2),('c',3)]
|
||||
```
|
||||
|
||||
And you can use list comprehensions with Strings.
|
||||
|
||||
```haskell
|
||||
count :: Char -> String -> Int
|
||||
count x xs = length [x' | x' <- xs, x == x']
|
||||
|
||||
count 'a' "paragraph"
|
||||
-- 3
|
||||
```
|
||||
41
portfolio/pages/nl/software/code/blazor/commands.md
Normal file
41
portfolio/pages/nl/software/code/blazor/commands.md
Normal file
@ -0,0 +1,41 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "Blazor commands"
|
||||
code: "Blazor"
|
||||
---
|
||||
|
||||
A collection of commands useful to work with blazor web applications.
|
||||
|
||||
|
||||
* Create a new application.
|
||||
|
||||
`dotnet new blazor -o BlazorWebAppMovies`
|
||||
|
||||
* Compile and run the application, and hot-reload upon changes.
|
||||
|
||||
`dotnet watch`
|
||||
|
||||
* VS Code build:
|
||||
|
||||
Command Palette (Ctrl+Shift+P), use the `.NET: Build` command to build the app.
|
||||
|
||||
* Create gitignore file:
|
||||
|
||||
`dotnet new gitignore`
|
||||
|
||||
* [Scaffolding example](https://learn.microsoft.com/en-us/aspnet/core/blazor/tutorials/movie-database-app/part-2?view=aspnetcore-8.0&pivots=vsc#scaffold-the-model):
|
||||
|
||||
`dotnet aspnet-codegenerator blazor CRUD -dbProvider sqlite -dc BlazorWebAppMovies.Data.BlazorWebAppMoviesContext -m Movie -outDir Components/Pages`
|
||||
|
||||
|
||||
### Entity framework
|
||||
|
||||
* Create a migration, this is also used when creating a new migration when the model has changed.
|
||||
|
||||
`dotnet ef migrations add InitialCreate`
|
||||
|
||||
* Update the database:
|
||||
|
||||
`dotnet ef database update`
|
||||
|
||||
49
portfolio/pages/nl/software/code/csharp/strings.md
Normal file
49
portfolio/pages/nl/software/code/csharp/strings.md
Normal file
@ -0,0 +1,49 @@
|
||||
## Strings
|
||||
|
||||
#### Verbatim string with @:
|
||||
|
||||
Preserves whitespace and characters like '\' do not need to be escaped.
|
||||
|
||||
```c#
|
||||
Console.WriteLine(@" c:\source\repos
|
||||
(this is where your code goes)");
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
> c:\source\repos
|
||||
> (this is where your code goes)
|
||||
```
|
||||
|
||||
#### Escaped Unicode
|
||||
|
||||
Use the **\u** plus a four-character code to represent Unicode characters (UTF-16) in a string.
|
||||
|
||||
[Japanese UTF-16 table](http://www.rikai.com/library/kanjitables/kanji_codes.unicode.shtml)
|
||||
|
||||
```c#
|
||||
Console.WriteLine("\u3053\u3093\u306B\u3061\u306F World!");
|
||||
```
|
||||
|
||||
Output (UTF-16):
|
||||
```
|
||||
> こんにちは World!
|
||||
```
|
||||
|
||||
```c#
|
||||
// To generate Japanese invoices:
|
||||
Console.Write("\n\n\u65e5\u672c\u8a9e\u306e\u8acb\u6c42\u66f8\u3092\u751f\u6210\u3059\u308b\u306b\u306f\uff1a");
|
||||
```
|
||||
|
||||
Output (UTF-16):
|
||||
```
|
||||
> 日本語の請求書を生成するには:
|
||||
```
|
||||
|
||||
#### String interpolation
|
||||
|
||||
Can be combined with verbatim strings.
|
||||
|
||||
```c#
|
||||
Console.WriteLine($@"C:\Output\{projectName}\Data");
|
||||
```
|
||||
10
portfolio/pages/nl/software/code/csharp/types.md
Normal file
10
portfolio/pages/nl/software/code/csharp/types.md
Normal file
@ -0,0 +1,10 @@
|
||||
## Types
|
||||
|
||||
Float Type Precision
|
||||
|
||||
float ~6-9 digits 0.25F
|
||||
double ~15-17 digits 0.25
|
||||
decimal 28-29 digits 0.25M
|
||||
|
||||
Both lowercase 'f' or 'F' can be used, same for 'm' and 'M'.
|
||||
|
||||
8
portfolio/pages/nl/software/code/elm/composition.md
Normal file
8
portfolio/pages/nl/software/code/elm/composition.md
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "Composition"
|
||||
code: "Elm"
|
||||
---
|
||||
|
||||
[Elm composition operators << and >>](https://package.elm-lang.org/packages/elm/core/latest/Basics#(%3C%3C))
|
||||
59
portfolio/pages/nl/software/code/elm/dry.md
Normal file
59
portfolio/pages/nl/software/code/elm/dry.md
Normal file
@ -0,0 +1,59 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "DRY"
|
||||
code: "Elm"
|
||||
---
|
||||
|
||||
DRY means: "[Don't Repeat Yourself](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)".
|
||||
|
||||
This page contains some common mistakes I make when writing Elm code and how I processed feedback afterwards to improve it.
|
||||
|
||||
|
||||
```elm
|
||||
let
|
||||
render item =
|
||||
case warning item of
|
||||
Just (Error tooltip) ->
|
||||
[ Html.text <| text item
|
||||
, Html.i
|
||||
[ HtmlAttributes.class "icon-error"
|
||||
, HtmlAttributes.title tooltip
|
||||
]
|
||||
]
|
||||
-- Another case, very similar to the one above.
|
||||
Just (Warning tooltip) ->
|
||||
[ Html.text <| text item
|
||||
, Html.i
|
||||
[ HtmlAttributes.class "icon-warning"
|
||||
, HtmlAttributes.title <| getWarningTooltip tooltip
|
||||
]
|
||||
]
|
||||
|
||||
Nothing ->
|
||||
[ Html.text <| text item ]
|
||||
|
||||
```
|
||||
|
||||
```elm
|
||||
let
|
||||
render item =
|
||||
let
|
||||
createHtml class tooltip =
|
||||
[ Html.text <| text item
|
||||
, Html.i
|
||||
[ HtmlAttributes.class class
|
||||
, HtmlAttributes.title tooltip
|
||||
]
|
||||
]
|
||||
in
|
||||
case warning item of
|
||||
Just (Error tooltip) ->
|
||||
createHtml "icon-error" tooltip
|
||||
|
||||
Just (Warning tooltip) ->
|
||||
createHtml "icon-warning" (getWarningTooltip tooltip)
|
||||
|
||||
Nothing ->
|
||||
[ Html.text <| text item ]
|
||||
```
|
||||
33
portfolio/pages/nl/software/code/elm/formatting.md
Normal file
33
portfolio/pages/nl/software/code/elm/formatting.md
Normal file
@ -0,0 +1,33 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "Formatting"
|
||||
code: "Elm"
|
||||
---
|
||||
|
||||
You can add a docstring to an elm function like this:
|
||||
|
||||
```elm
|
||||
|
||||
|
||||
{- Render the Elm icon. -}
|
||||
|
||||
|
||||
elmIcon : E.Element msg
|
||||
elmIcon =
|
||||
|
||||
```
|
||||
|
||||
But upon formatting, 2 new lines are automatically added.
|
||||
|
||||
By adding a "|" pipe character, the docstring will get appended to the top op the function header.
|
||||
|
||||
```elm
|
||||
|
||||
|
||||
{-| Render the Elm icon.
|
||||
-}
|
||||
elmIcon : E.Element msg
|
||||
elmIcon =
|
||||
|
||||
```
|
||||
93
portfolio/pages/nl/software/code/elm/maybeandthen.md
Normal file
93
portfolio/pages/nl/software/code/elm/maybeandthen.md
Normal file
@ -0,0 +1,93 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "Maybe AndThen"
|
||||
code: "Elm"
|
||||
---
|
||||
|
||||
Given are these functions, **hasPrecedingReleasedVersions** and **getSelectedItemIndex**, need to be optimized.
|
||||
|
||||
|
||||
```elm
|
||||
|
||||
hasPrecedingReleasedVersions =
|
||||
case getSelectedItemIndex data.versionData of
|
||||
Just index ->
|
||||
Array.slice 0 index data.versionData.allItems
|
||||
|> Array.toList
|
||||
|> List.any
|
||||
(\item ->
|
||||
case item of
|
||||
ReleasedVersion _ ->
|
||||
True
|
||||
_ ->
|
||||
False
|
||||
)
|
||||
Nothing ->
|
||||
False
|
||||
```
|
||||
|
||||
Currently, **getSelectedItemIndex** is defined as such:
|
||||
|
||||
```elm
|
||||
|
||||
getSelectedItemIndex : Model id -> Maybe Int
|
||||
getSelectedItemIndex model =
|
||||
case getSelectedItem model of
|
||||
Just selected ->
|
||||
Array.toIndexedList model.allItems
|
||||
|> List.filter (\( _, item ) -> item == selected)
|
||||
|> List.head
|
||||
|> Maybe.map Tuple.first
|
||||
|
||||
Nothing ->
|
||||
Nothing
|
||||
|
||||
|
||||
```
|
||||
|
||||
But using [Maybe.andThen](https://package.elm-lang.org/packages/elm/core/latest/Maybe#andThen) will allow to get rid of the **Nothing -> Nothing** here.
|
||||
Also the **List.filter** and **List.head** combination can be shortened with a **List.find**.
|
||||
|
||||
```elm
|
||||
|
||||
getSelectedItemIndex : Model id -> Maybe Int
|
||||
getSelectedItemIndex model =
|
||||
getSelectedItem model
|
||||
|> Maybe.andThen
|
||||
(\selected ->
|
||||
Array.toIndexedList model.allItems
|
||||
|> List.find (\( _, item ) -> item == selected)
|
||||
|> Maybe.map Tuple.first
|
||||
)
|
||||
|
||||
|
||||
```
|
||||
|
||||
Finally, define a custom funcion to determine the boolean:
|
||||
|
||||
```elm
|
||||
|
||||
itemIsReleased : VersionData id -> Bool
|
||||
itemIsReleased versionData =
|
||||
case versionData of
|
||||
WorkingVersion _ ->
|
||||
False
|
||||
ReleasedVersion
|
||||
True
|
||||
|
||||
```
|
||||
|
||||
The original function can now be changed to:
|
||||
|
||||
```elm
|
||||
|
||||
hasPrecedingReleasedVersions =
|
||||
case getSelectedItemIndex data.versionData of
|
||||
Just index ->
|
||||
Array.slice 0 index data.versionData.allItems
|
||||
|> Array.toList
|
||||
|> List.any itemIsReleased
|
||||
Nothing ->
|
||||
False
|
||||
```
|
||||
50
portfolio/pages/nl/software/code/elm/maybemap.md
Normal file
50
portfolio/pages/nl/software/code/elm/maybemap.md
Normal file
@ -0,0 +1,50 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "Maybe Map"
|
||||
code: "Elm"
|
||||
---
|
||||
|
||||
Here, a tooltip title attribute needs to be added if it is **Just**.
|
||||
|
||||
```elm
|
||||
let
|
||||
divAttributes =
|
||||
[ HA.classList
|
||||
[ ( "my-div", True ) ]
|
||||
]
|
||||
|
||||
combinedAttributes =
|
||||
case settings.tooltip of
|
||||
Just tooltip ->
|
||||
divAttributes ++ [ HA.title tooltip ]
|
||||
|
||||
Nothing ->
|
||||
divAttributes
|
||||
in
|
||||
H.div
|
||||
combinedAttributes
|
||||
[ content ]
|
||||
|
||||
```
|
||||
|
||||
This can be easier written with the [Maybe.map](https://package.elm-lang.org/packages/elm/core/latest/Maybe#map) and [Maybe.withDefault](https://package.elm-lang.org/packages/elm/core/latest/Maybe#withDefault) functions.
|
||||
|
||||
```elm
|
||||
|
||||
let
|
||||
divAttributes =
|
||||
[ HA.classList
|
||||
[ ( "my-div", True ) ]
|
||||
]
|
||||
|
||||
tooltipAttribute =
|
||||
Maybe.map (\tooltip -> [ HA.title tooltip ]) settings.tooltip |> Maybe.withDefault []
|
||||
-- or you can do:
|
||||
settings.tooltip |> Maybe.map (\tooltip -> [ HA.title tooltip ]) |> Maybe.withDefault []
|
||||
|
||||
in
|
||||
H.div
|
||||
(divAttributes ++ tooltipAttribute)
|
||||
[ content ]
|
||||
```
|
||||
36
portfolio/pages/nl/software/code/haskell/caesar-cipher.md
Normal file
36
portfolio/pages/nl/software/code/haskell/caesar-cipher.md
Normal file
@ -0,0 +1,36 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "Caesar Cipher"
|
||||
code: "Haskell"
|
||||
---
|
||||
|
||||
The implementation of the [Caesar's Cipher](https://en.wikipedia.org/wiki/Caesar_cipher) in Haskell.
|
||||
|
||||
*Source*: [Programming in Haskell, by Graham Hutton](https://people.cs.nott.ac.uk/pszgmh/pih.html)
|
||||
|
||||
```haskell
|
||||
import Data.Char
|
||||
import Prelude
|
||||
|
||||
let2int :: Char -> Int
|
||||
let2int c | isLower c = ord c - ord 'a'
|
||||
| otherwise = ord c - ord 'A'
|
||||
|
||||
int2let :: Int -> Bool -> Char
|
||||
int2let n isLowercase = chr (ord (if isLowercase then 'a' else 'A') + n)
|
||||
|
||||
shift :: Int -> Char -> Char
|
||||
shift n c | isLower c = int2let ((let2int c + n) `mod` 26) (isLower c)
|
||||
| isUpper c = int2let ((let2int c + n) `mod` 26) (isLower c)
|
||||
| otherwise = c
|
||||
|
||||
encode :: Int -> String -> String
|
||||
encode n xs = [shift n x | x <- xs]
|
||||
|
||||
|
||||
ghci> encode 5 "This is a Caesar Cipher"
|
||||
-- "Ymnx nx f Hfjxfw Hnumjw"
|
||||
ghci> encode (-5) "Ymnx nx f Hfjxfw Hnumjw"
|
||||
-- "This is a Caesar Cipher"
|
||||
```
|
||||
@ -0,0 +1,44 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "Conditional expressions and Guarded equations"
|
||||
code: "Haskell"
|
||||
---
|
||||
|
||||
### Conditional expressions
|
||||
|
||||
```haskell
|
||||
signum :: Int -> Int
|
||||
signum n = if n < 0 then -1 else
|
||||
if n == 0 then 0 else 1
|
||||
```
|
||||
|
||||
And a **safetail** function, where an empty list is returned instead of an error when given an empty list.
|
||||
|
||||
```haskell
|
||||
safetail :: [a] -> [a]
|
||||
safetail xs = if length xs > 0 then tail xs else []
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Guarded equations
|
||||
|
||||
An alternative to conditional expressions, functions can be defined with guarded equations.
|
||||
|
||||
An example of the **signum** function:
|
||||
|
||||
```haskell
|
||||
signum :: Int -> Int
|
||||
signum n | n < 0 = -1
|
||||
| n == 0 = 0
|
||||
| otherwise = 1
|
||||
```
|
||||
|
||||
Here is **safetail** with guarded equations:
|
||||
|
||||
```haskell
|
||||
safetail :: [a] -> [a]
|
||||
safetail xs | length xs > 0 = tail xs
|
||||
| otherwise = []
|
||||
```
|
||||
@ -0,0 +1,71 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "Curried functions"
|
||||
code: "Haskell"
|
||||
---
|
||||
|
||||
A function can return another function.
|
||||
|
||||
```haskell
|
||||
add' :: Int -> (Int -> Int)
|
||||
add' x y = x+y
|
||||
```
|
||||
|
||||
Here, **add'** is a function that takes an **Int** for an argument and results in a function of type: **Int -> Int**.
|
||||
The function definition takes an integer **x**, followed by an integer **y**, it can be [curried](https://en.wikipedia.org/wiki/Currying).
|
||||
|
||||
```haskell
|
||||
addThree = add' 3 -- This is now a function with type: Int -> Int
|
||||
result = addThree 5 -- Evaluates to 8
|
||||
```
|
||||
|
||||
Another example,
|
||||
|
||||
```haskell
|
||||
mult :: Int -> (Int -> (Int -> Int))
|
||||
mult x y z = x*y*z
|
||||
```
|
||||
|
||||
And is applied as following:
|
||||
|
||||
```haskell
|
||||
mult x y z
|
||||
-- Means same as:
|
||||
((mult x) y) z
|
||||
```
|
||||
|
||||
When used, it is like:
|
||||
|
||||
```haskell
|
||||
multTwo = mult 2 -- This is now a function with type: Int -> (Int -> Int)
|
||||
multTwoThree = multTwo 3 -- This is: Int -> Int
|
||||
result = multTwoThree 4 -- Evaluates to 2 * 3 * 4 = 24
|
||||
|
||||
-- or just:
|
||||
|
||||
result = mult 2 3 4 -- Also evaluates to 24
|
||||
```
|
||||
|
||||
**Partial application** is about using curried functions, applying only some arguments and getting back a new function.
|
||||
|
||||
```haskell
|
||||
double = mult 2 -- This is now a function with type: Int -> (Int -> Int)
|
||||
|
||||
result = double 3 4 -- Evaluates to 2 * 3 * 4 = 24
|
||||
|
||||
quadruple = double 2 -- Now quadruple :: Int -> Int
|
||||
result = quadruple 3 -- Evaluates to 2 * 2 * 3 = 12
|
||||
```
|
||||
|
||||
The arrow function **->** in Haskell types is assumed to associate from the right.
|
||||
|
||||
```haskell
|
||||
Int -> Int -> Int -> Int
|
||||
|
||||
-- is:
|
||||
|
||||
Int -> (Int -> (Int -> Int))
|
||||
```
|
||||
|
||||
So, unless tuples are required, all functions in Haskell with multiple arguments are actually defined as curried functions, with a way to reduce excessive parenthesis.
|
||||
@ -0,0 +1,257 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "Programming in Haskell by Graham Hutton"
|
||||
code: "Haskell"
|
||||
---
|
||||
|
||||
This book is what I used to learn the programming language Haskell. This page contains all my exercise answers.
|
||||
|
||||
*Source*: [Programming in Haskell, by Graham Hutton](https://people.cs.nott.ac.uk/pszgmh/pih.html)
|
||||
|
||||
* [Chapter 4 - Defining functions](#Chapter-4)
|
||||
* [Chapter 5 - List comprehensions](#Chapter-5)
|
||||
* [Chapter 6 - Recursive functions](#Chapter-6)
|
||||
|
||||
---
|
||||
|
||||
#### Chapter-4
|
||||
##### Defining functions
|
||||
|
||||
###### exercise 1
|
||||
|
||||
```haskell
|
||||
halve :: [Int] -> ([Int], [Int])
|
||||
halve xs =
|
||||
(take n xs, drop n xs)
|
||||
where n = length xs `div` 2
|
||||
|
||||
halve :: [Int] -> ([Int], [Int])
|
||||
halve xs =
|
||||
splitAt (length xs `div` 2) xs
|
||||
```
|
||||
|
||||
###### exercise 2
|
||||
|
||||
```haskell
|
||||
-- a (head & tail)
|
||||
third :: [a] -> a
|
||||
third xs = head (tail (tail xs))
|
||||
|
||||
-- b (list indexing)
|
||||
third :: [a] -> a
|
||||
third xs = xs !! 2
|
||||
|
||||
-- c (pattern matching)
|
||||
third :: [a] -> a
|
||||
third (_:_:a:_) = a
|
||||
```
|
||||
|
||||
###### exercise 3
|
||||
|
||||
```haskell
|
||||
-- a (conditional expression)
|
||||
safetail :: [a] -> [a]
|
||||
safetail xs = if length xs > 0 then tail xs else []
|
||||
|
||||
-- b (guarded equation)
|
||||
safetail :: [a] -> [a]
|
||||
safetail xs | length xs > 0 = tail xs
|
||||
| otherwise = []
|
||||
|
||||
-- c (pattern matching)
|
||||
safetail :: [a] -> [a]
|
||||
safetail [] = []
|
||||
safetail xs = tail xs
|
||||
-- or:
|
||||
-- safetail (_:xs) = xs
|
||||
```
|
||||
|
||||
###### exercise 4
|
||||
|
||||
```haskell
|
||||
(||) :: Bool -> Bool -> Bool
|
||||
True || _ = True
|
||||
_ || True = True
|
||||
_ = False
|
||||
```
|
||||
|
||||
###### exercise 5
|
||||
|
||||
```haskell
|
||||
-- Use conditional expressions to define &&.
|
||||
(<#>) :: Bool -> Bool -> Bool
|
||||
a <#> b =
|
||||
if a then
|
||||
if b then True else False
|
||||
else
|
||||
False
|
||||
```
|
||||
|
||||
###### exercise 6
|
||||
|
||||
```haskell
|
||||
(<#>) :: Bool -> Bool -> Bool
|
||||
a <#> b =
|
||||
if a then b else False
|
||||
```
|
||||
|
||||
###### exercise 7
|
||||
|
||||
```haskell
|
||||
mult :: Int -> Int -> Int -> Int
|
||||
mult x y z = x*y*z
|
||||
|
||||
-- rewritten to use lambda functions.
|
||||
mult :: Int -> (Int -> (Int -> Int))
|
||||
mult = \x -> (\y -> (\z -> x * y * z))
|
||||
```
|
||||
|
||||
###### exercise 8
|
||||
|
||||
[Luhn algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm)
|
||||
|
||||
```haskell
|
||||
luhnDouble :: Int -> Int
|
||||
luhnDouble x = x * 2 `mod` 9
|
||||
|
||||
luhn :: Int -> Int -> Int -> Int -> Bool
|
||||
luhn a b c d =
|
||||
sum ((map luhnDouble [a,c]) ++ [b,d]) `mod` 10 == 0
|
||||
|
||||
--ghci> luhn 1 7 8 4
|
||||
--True
|
||||
--ghci> luhn 4 7 8 3
|
||||
--False
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### Chapter-5
|
||||
##### List comprehensions
|
||||
|
||||
* exercise 1
|
||||
|
||||
```haskell
|
||||
sum [x^2 | x <- [0..100]]
|
||||
-- 338350
|
||||
```
|
||||
|
||||
###### exercise 2
|
||||
|
||||
```haskell
|
||||
grid :: Int -> Int -> [(Int, Int)]
|
||||
grid n m =
|
||||
[(x,y) | x <- [0..n], y <- [0..m]]
|
||||
|
||||
ghci> grid 1 2
|
||||
-- [(0,0),(0,1),(0,2),(1,0),(1,1),(1,2)]
|
||||
```
|
||||
|
||||
###### exercise 3
|
||||
|
||||
```haskell
|
||||
square :: Int -> [(Int,Int)]
|
||||
square n =
|
||||
[(x,y) | (x,y) <- grid n n, x /= y]
|
||||
|
||||
ghci> square 2
|
||||
-- [(0,1),(0,2),(1,0),(1,2),(2,0),(2,1)]
|
||||
```
|
||||
|
||||
###### exercise 4
|
||||
|
||||
```haskell
|
||||
replicate :: Int -> a -> [a]
|
||||
replicate n item =
|
||||
[item | _ <- [1..n]]
|
||||
|
||||
ghci> replicate 4 "test"
|
||||
-- ["test","test","test","test"]
|
||||
```
|
||||
|
||||
###### exercise 5
|
||||
|
||||
[Pythagorean theorem](https://en.wikipedia.org/wiki/Pythagorean_theorem)
|
||||
|
||||
```haskell
|
||||
isPythagorean :: Int -> Int -> Int -> Bool
|
||||
isPythagorean x y z =
|
||||
x^2 + y^2 == z^2
|
||||
|
||||
pyths :: Int -> [(Int,Int,Int)]
|
||||
pyths n =
|
||||
[(x,y,z) | x <- [1..n], y <- [1..n], z <- [1..n], isPythagorean x y z]
|
||||
|
||||
ghci> pyths 10
|
||||
-- [(3,4,5),(4,3,5),(6,8,10),(8,6,10)]
|
||||
```
|
||||
|
||||
###### exercise 6
|
||||
|
||||
[Perfect number](https://en.wikipedia.org/wiki/Perfect_number)
|
||||
|
||||
```haskell
|
||||
factors :: Int -> [Int]
|
||||
factors n = [x | x <- [1..n], n `mod` x == 0]
|
||||
|
||||
perfects :: Int -> [Int]
|
||||
perfects limit =
|
||||
[x | x <- [1..limit], sum (factors x) - x == x]
|
||||
|
||||
ghci> perfects 10000
|
||||
-- [6,28,496,8128]
|
||||
```
|
||||
|
||||
###### exercise 7
|
||||
*(I did not understand this one)*
|
||||
|
||||
###### exercise 8
|
||||
|
||||
Use the **find** library function in [Data.List 9.8.2](https://downloads.haskell.org/ghc/9.8.2/docs/libraries/base-4.19.1.0-179c/Data-List.html#v:find)
|
||||
|
||||
```haskell
|
||||
find :: (a -> Bool) -> [a] -> Maybe a
|
||||
-- The find function takes a predicate and a list and returns the first element in the list matching the predicate, or Nothing if there is no such element.
|
||||
```
|
||||
|
||||
```haskell
|
||||
positions :: Eq a => a -> [a] -> [Int]
|
||||
positions x xs =
|
||||
[i | (x',i) <- zip xs [0..], x == x']
|
||||
|
||||
-- using find function, though I doubt its correct...
|
||||
|
||||
positions :: Eq a => a -> [a] -> [Int]
|
||||
positions x xs =
|
||||
[i | (x',i) <- zip xs [0..], isJust (find (==x) [x'])]
|
||||
|
||||
positions 2 [1,1,0,2,46,6,8,9,2,3,4,2,4,9,2]
|
||||
-- [3,8,11,14]
|
||||
|
||||
-- You can also use:
|
||||
positions :: Eq a => a -> [a] -> [Int]
|
||||
positions x = elemIndices x
|
||||
```
|
||||
|
||||
###### exercise 9
|
||||
|
||||
[Scalar product](https://en.wikipedia.org/wiki/Dot_product)
|
||||
|
||||
```haskell
|
||||
scalarproduct :: [Int] -> [Int] -> Int
|
||||
scalarproduct xs ys =
|
||||
sum [x*y | (x,y) <- zip xs ys]
|
||||
|
||||
ghci> scalarproduct [1,2,3] [4,5,6]
|
||||
-- 32
|
||||
```
|
||||
|
||||
###### execise 10
|
||||
|
||||
[Caesar's Cipher](./caesar-cipher)
|
||||
|
||||
---
|
||||
|
||||
#### Chapter-6
|
||||
##### Recursive functions
|
||||
@ -0,0 +1,52 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "Lambda expressions"
|
||||
code: "Haskell"
|
||||
---
|
||||
|
||||
You can define a function like:
|
||||
|
||||
```haskell
|
||||
double :: Int -> Int
|
||||
double x = x + x
|
||||
```
|
||||
|
||||
Which can also be written as an anonymous function:
|
||||
|
||||
```haskell
|
||||
\x -> x + x
|
||||
```
|
||||
|
||||
Here, the **\\** symbol represents the Greek letter lambda: **λ**. This is derived from [lambda calculus](https://en.wikipedia.org/wiki/Lambda_calculus).
|
||||
|
||||
Lambda expressions can be used to more explicitly state that a function is returned.
|
||||
|
||||
Consider:
|
||||
|
||||
```haskell
|
||||
const :: a -> b -> a
|
||||
const x _ = x
|
||||
```
|
||||
|
||||
This can be written using a lambda expression and added parenthesis in the type definition. This is more explicit in that a function is being returned.
|
||||
|
||||
```haskell
|
||||
const :: a -> (b -> a)
|
||||
const x = \_ -> x
|
||||
```
|
||||
|
||||
And as an anonymous function. Consider the difference between these similar functions that return a list of odd numbers:
|
||||
|
||||
```haskell
|
||||
odds :: Int -> [Int]
|
||||
odds n = map f [0..n-1]
|
||||
where f x = x*2 + 1
|
||||
|
||||
odds :: Int -> [Int]
|
||||
odds n = map (\x -> x*2 + 1) [0..n-1]
|
||||
|
||||
-- > odds 15
|
||||
-- > [1,3,5,7,9,11,13,15,17,19,21,23,25,27,29]
|
||||
```
|
||||
|
||||
124
portfolio/pages/nl/software/code/haskell/lists.md
Normal file
124
portfolio/pages/nl/software/code/haskell/lists.md
Normal file
@ -0,0 +1,124 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "Lists"
|
||||
code: "Haskell"
|
||||
---
|
||||
|
||||
Lists are constructed one element at a time starting from an empty **[]** list using the *cons* operator **:**. For example, **[1,2,3]** can be decomposed as:
|
||||
|
||||
```haskell
|
||||
[1,2,3]
|
||||
--
|
||||
1 : [2,3]
|
||||
--
|
||||
1 : (2 : [3])
|
||||
--
|
||||
1 : (2 : (3 : []))
|
||||
```
|
||||
|
||||
To verify if a list with 3 numbers starts with the integer **1**, you can use pattern matching.
|
||||
|
||||
```haskell
|
||||
startsWithOne :: [Int] -> Bool
|
||||
startsWithOne [1, _, _] = True
|
||||
startsWithOne _ = False
|
||||
```
|
||||
|
||||
### Access elements
|
||||
|
||||
To access an element in a list, the indexing operator **!!** can be used.
|
||||
|
||||
```haskell
|
||||
-- Get the third element of a list.
|
||||
third :: [a] -> a
|
||||
third xs = xs !! 2
|
||||
```
|
||||
|
||||
### list comprehension
|
||||
|
||||
* Wikipedia: [List comprehension](https://en.wikipedia.org/wiki/List_comprehension).
|
||||
|
||||
|
||||
```haskell
|
||||
ghci> [x^2 | x <- [1..6]]
|
||||
-- [1,4,9,16,25,36]
|
||||
```
|
||||
|
||||
* The **|** symbol is read as: "*such that*".
|
||||
* The **<-** symbol is read as: "*drawn from*".
|
||||
* And **x <- [1..6]** is called a: "*generator*".
|
||||
|
||||
A list comprehension can have more than one generator.
|
||||
|
||||
```haskell
|
||||
ghci> [(x,y) | x <- [1,2,3], y <- [4,5]]
|
||||
-- [(1,4),(1,5),(2,4),(2,5),(3,4),(3,5)]
|
||||
```
|
||||
|
||||
Examples of list comprehensions:
|
||||
|
||||
```haskell
|
||||
halve :: [Int] -> ([Int], [Int])
|
||||
halve xs =
|
||||
([x | x <- xs, x < 4], [x | x <- xs, x >= 4])
|
||||
|
||||
-- halve [1,2,3,4,5,6]
|
||||
-- ([1,2,3],[4,5,6])
|
||||
```
|
||||
|
||||
How to actually halve the list properly:
|
||||
|
||||
```haskell
|
||||
halve :: [Int] -> ([Int], [Int])
|
||||
halve xs =
|
||||
(take n xs, drop n xs)
|
||||
where n = length xs `div` 2
|
||||
-- or
|
||||
splitAt (length xs `div` 2) xs
|
||||
```
|
||||
|
||||
Here the **length** function replaces all elements with a 1 and sums the total:
|
||||
|
||||
```haskell
|
||||
length :: [a] -> Int
|
||||
length xs = sum [1 | _ <- xs]
|
||||
length [1,4,8,90]
|
||||
-- 4
|
||||
```
|
||||
|
||||
You can use logical expressions as a **guard**, to filter values created by list comprehensions.
|
||||
|
||||
```haskell
|
||||
factors :: Int -> [Int]
|
||||
factors n = [x | x <- [1..n], n `mod` x == 0]
|
||||
|
||||
factors 20
|
||||
-- [1,2,4,5,10,20]
|
||||
factors 13
|
||||
-- [1,13]
|
||||
```
|
||||
|
||||
And you can use this **factors** function to determine **prime** numbers.
|
||||
|
||||
* Wikipedia: [Prime number](https://en.wikipedia.org/wiki/Prime_number)
|
||||
|
||||
```haskell
|
||||
prime :: Int -> Bool
|
||||
prime n = factors n == [1,n]
|
||||
|
||||
prime 15
|
||||
--False
|
||||
prime 13
|
||||
-- True
|
||||
```
|
||||
And with this **prime** function, we can use list comprehension to determine a range of prime numbers!
|
||||
|
||||
```haskell
|
||||
primes :: Int -> [Int]
|
||||
primes n = [x | x <- [2..n], prime x]
|
||||
|
||||
primes 50
|
||||
-- [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47]
|
||||
```
|
||||
|
||||
14
portfolio/pages/nl/software/code/haskell/pattern-matching.md
Normal file
14
portfolio/pages/nl/software/code/haskell/pattern-matching.md
Normal file
@ -0,0 +1,14 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "Pattern matching"
|
||||
code: "Haskell"
|
||||
---
|
||||
|
||||
An example to determine the third element of a list, (with at least 3 elements):
|
||||
|
||||
```haskell
|
||||
third :: [a] -> a
|
||||
third (_:_:x:_) = x
|
||||
```
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "Recursive functions"
|
||||
code: "Haskell"
|
||||
---
|
||||
|
||||
Recursion is the basic mechanism for looping in Haskell.
|
||||
|
||||
Determine the [factorial](https://en.wikipedia.org/wiki/Factorial).
|
||||
|
||||
```haskell
|
||||
factorial :: Int -> Int
|
||||
factorial 0 = 1
|
||||
factorial n = n * factorial (n-1)
|
||||
```
|
||||
|
||||
The factorial of 3, actually is calculated as such:
|
||||
|
||||
```haskell
|
||||
factorial 3
|
||||
3 * factorial 2
|
||||
3 * (2 * factorial 1)
|
||||
3 * (2 * (1 * factorial 0))
|
||||
3 * (2 * (1 * 1))
|
||||
```
|
||||
|
||||
38
portfolio/pages/nl/software/code/haskell/strings.md
Normal file
38
portfolio/pages/nl/software/code/haskell/strings.md
Normal file
@ -0,0 +1,38 @@
|
||||
---
|
||||
logosub: "Software"
|
||||
language: "en"
|
||||
title: "Strings"
|
||||
code: "Haskell"
|
||||
---
|
||||
|
||||
Strings are not primitive types, but a list of characters.
|
||||
|
||||
For example,
|
||||
|
||||
```haskell
|
||||
"abc" :: String
|
||||
-- is actually:
|
||||
['a','b','c'] :: [Char]
|
||||
```
|
||||
Because of this, polymorphic functions on lists, can be used with strings.
|
||||
|
||||
```haskell
|
||||
"abcde" !! 2
|
||||
-- 'c'
|
||||
take 3 "abcde"
|
||||
-- "abc"
|
||||
length "abcde"
|
||||
-- 5
|
||||
zip "abc" [1,2,3,4]
|
||||
-- [('a',1),('b',2),('c',3)]
|
||||
```
|
||||
|
||||
And you can use list comprehensions with Strings.
|
||||
|
||||
```haskell
|
||||
count :: Char -> String -> Int
|
||||
count x xs = length [x' | x' <- xs, x == x']
|
||||
|
||||
count 'a' "paragraph"
|
||||
-- 3
|
||||
```
|
||||
Loading…
x
Reference in New Issue
Block a user