diff --git a/portfolio/pages/jp/software/code/blazor/commands.md b/portfolio/pages/jp/software/code/blazor/commands.md new file mode 100644 index 0000000..20a7f84 --- /dev/null +++ b/portfolio/pages/jp/software/code/blazor/commands.md @@ -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` + diff --git a/portfolio/pages/jp/software/code/csharp/strings.md b/portfolio/pages/jp/software/code/csharp/strings.md new file mode 100644 index 0000000..3828dd1 --- /dev/null +++ b/portfolio/pages/jp/software/code/csharp/strings.md @@ -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"); +``` \ No newline at end of file diff --git a/portfolio/pages/jp/software/code/csharp/types.md b/portfolio/pages/jp/software/code/csharp/types.md new file mode 100644 index 0000000..dbba32e --- /dev/null +++ b/portfolio/pages/jp/software/code/csharp/types.md @@ -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'. + diff --git a/portfolio/pages/jp/software/code/elm/composition.md b/portfolio/pages/jp/software/code/elm/composition.md new file mode 100644 index 0000000..1084258 --- /dev/null +++ b/portfolio/pages/jp/software/code/elm/composition.md @@ -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)) diff --git a/portfolio/pages/jp/software/code/elm/dry.md b/portfolio/pages/jp/software/code/elm/dry.md new file mode 100644 index 0000000..df5bae8 --- /dev/null +++ b/portfolio/pages/jp/software/code/elm/dry.md @@ -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 ] +``` diff --git a/portfolio/pages/jp/software/code/elm/formatting.md b/portfolio/pages/jp/software/code/elm/formatting.md new file mode 100644 index 0000000..737c151 --- /dev/null +++ b/portfolio/pages/jp/software/code/elm/formatting.md @@ -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 = + +``` diff --git a/portfolio/pages/jp/software/code/elm/maybeandthen.md b/portfolio/pages/jp/software/code/elm/maybeandthen.md new file mode 100644 index 0000000..c07b1a5 --- /dev/null +++ b/portfolio/pages/jp/software/code/elm/maybeandthen.md @@ -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 +``` \ No newline at end of file diff --git a/portfolio/pages/jp/software/code/elm/maybemap.md b/portfolio/pages/jp/software/code/elm/maybemap.md new file mode 100644 index 0000000..27ac631 --- /dev/null +++ b/portfolio/pages/jp/software/code/elm/maybemap.md @@ -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 ] +``` \ No newline at end of file diff --git a/portfolio/pages/jp/software/code/haskell/caesar-cipher.md b/portfolio/pages/jp/software/code/haskell/caesar-cipher.md new file mode 100644 index 0000000..0993271 --- /dev/null +++ b/portfolio/pages/jp/software/code/haskell/caesar-cipher.md @@ -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" +``` \ No newline at end of file diff --git a/portfolio/pages/jp/software/code/haskell/conditional-expressions-and-guarded-equations.md b/portfolio/pages/jp/software/code/haskell/conditional-expressions-and-guarded-equations.md new file mode 100644 index 0000000..9ccdf39 --- /dev/null +++ b/portfolio/pages/jp/software/code/haskell/conditional-expressions-and-guarded-equations.md @@ -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 = [] +``` \ No newline at end of file diff --git a/portfolio/pages/jp/software/code/haskell/curried-functions.md b/portfolio/pages/jp/software/code/haskell/curried-functions.md new file mode 100644 index 0000000..36c0237 --- /dev/null +++ b/portfolio/pages/jp/software/code/haskell/curried-functions.md @@ -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. diff --git a/portfolio/pages/jp/software/code/haskell/graham-hutton-answers.md b/portfolio/pages/jp/software/code/haskell/graham-hutton-answers.md new file mode 100644 index 0000000..373d337 --- /dev/null +++ b/portfolio/pages/jp/software/code/haskell/graham-hutton-answers.md @@ -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 \ No newline at end of file diff --git a/portfolio/pages/jp/software/code/haskell/lambda-expressions.md b/portfolio/pages/jp/software/code/haskell/lambda-expressions.md new file mode 100644 index 0000000..e040b5b --- /dev/null +++ b/portfolio/pages/jp/software/code/haskell/lambda-expressions.md @@ -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] +``` + diff --git a/portfolio/pages/jp/software/code/haskell/lists.md b/portfolio/pages/jp/software/code/haskell/lists.md new file mode 100644 index 0000000..f095176 --- /dev/null +++ b/portfolio/pages/jp/software/code/haskell/lists.md @@ -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] +``` + diff --git a/portfolio/pages/jp/software/code/haskell/pattern-matching.md b/portfolio/pages/jp/software/code/haskell/pattern-matching.md new file mode 100644 index 0000000..b5b6b5f --- /dev/null +++ b/portfolio/pages/jp/software/code/haskell/pattern-matching.md @@ -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 +``` + diff --git a/portfolio/pages/jp/software/code/haskell/recursive-functions.md b/portfolio/pages/jp/software/code/haskell/recursive-functions.md new file mode 100644 index 0000000..398e438 --- /dev/null +++ b/portfolio/pages/jp/software/code/haskell/recursive-functions.md @@ -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)) +``` + diff --git a/portfolio/pages/jp/software/code/haskell/strings.md b/portfolio/pages/jp/software/code/haskell/strings.md new file mode 100644 index 0000000..64a3cf9 --- /dev/null +++ b/portfolio/pages/jp/software/code/haskell/strings.md @@ -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 +``` diff --git a/portfolio/pages/nl/software/code/blazor/commands.md b/portfolio/pages/nl/software/code/blazor/commands.md new file mode 100644 index 0000000..20a7f84 --- /dev/null +++ b/portfolio/pages/nl/software/code/blazor/commands.md @@ -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` + diff --git a/portfolio/pages/nl/software/code/csharp/strings.md b/portfolio/pages/nl/software/code/csharp/strings.md new file mode 100644 index 0000000..3828dd1 --- /dev/null +++ b/portfolio/pages/nl/software/code/csharp/strings.md @@ -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"); +``` \ No newline at end of file diff --git a/portfolio/pages/nl/software/code/csharp/types.md b/portfolio/pages/nl/software/code/csharp/types.md new file mode 100644 index 0000000..dbba32e --- /dev/null +++ b/portfolio/pages/nl/software/code/csharp/types.md @@ -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'. + diff --git a/portfolio/pages/nl/software/code/elm/composition.md b/portfolio/pages/nl/software/code/elm/composition.md new file mode 100644 index 0000000..1084258 --- /dev/null +++ b/portfolio/pages/nl/software/code/elm/composition.md @@ -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)) diff --git a/portfolio/pages/nl/software/code/elm/dry.md b/portfolio/pages/nl/software/code/elm/dry.md new file mode 100644 index 0000000..df5bae8 --- /dev/null +++ b/portfolio/pages/nl/software/code/elm/dry.md @@ -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 ] +``` diff --git a/portfolio/pages/nl/software/code/elm/formatting.md b/portfolio/pages/nl/software/code/elm/formatting.md new file mode 100644 index 0000000..737c151 --- /dev/null +++ b/portfolio/pages/nl/software/code/elm/formatting.md @@ -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 = + +``` diff --git a/portfolio/pages/nl/software/code/elm/maybeandthen.md b/portfolio/pages/nl/software/code/elm/maybeandthen.md new file mode 100644 index 0000000..c07b1a5 --- /dev/null +++ b/portfolio/pages/nl/software/code/elm/maybeandthen.md @@ -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 +``` \ No newline at end of file diff --git a/portfolio/pages/nl/software/code/elm/maybemap.md b/portfolio/pages/nl/software/code/elm/maybemap.md new file mode 100644 index 0000000..27ac631 --- /dev/null +++ b/portfolio/pages/nl/software/code/elm/maybemap.md @@ -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 ] +``` \ No newline at end of file diff --git a/portfolio/pages/nl/software/code/haskell/caesar-cipher.md b/portfolio/pages/nl/software/code/haskell/caesar-cipher.md new file mode 100644 index 0000000..0993271 --- /dev/null +++ b/portfolio/pages/nl/software/code/haskell/caesar-cipher.md @@ -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" +``` \ No newline at end of file diff --git a/portfolio/pages/nl/software/code/haskell/conditional-expressions-and-guarded-equations.md b/portfolio/pages/nl/software/code/haskell/conditional-expressions-and-guarded-equations.md new file mode 100644 index 0000000..9ccdf39 --- /dev/null +++ b/portfolio/pages/nl/software/code/haskell/conditional-expressions-and-guarded-equations.md @@ -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 = [] +``` \ No newline at end of file diff --git a/portfolio/pages/nl/software/code/haskell/curried-functions.md b/portfolio/pages/nl/software/code/haskell/curried-functions.md new file mode 100644 index 0000000..36c0237 --- /dev/null +++ b/portfolio/pages/nl/software/code/haskell/curried-functions.md @@ -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. diff --git a/portfolio/pages/nl/software/code/haskell/graham-hutton-answers.md b/portfolio/pages/nl/software/code/haskell/graham-hutton-answers.md new file mode 100644 index 0000000..373d337 --- /dev/null +++ b/portfolio/pages/nl/software/code/haskell/graham-hutton-answers.md @@ -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 \ No newline at end of file diff --git a/portfolio/pages/nl/software/code/haskell/lambda-expressions.md b/portfolio/pages/nl/software/code/haskell/lambda-expressions.md new file mode 100644 index 0000000..e040b5b --- /dev/null +++ b/portfolio/pages/nl/software/code/haskell/lambda-expressions.md @@ -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] +``` + diff --git a/portfolio/pages/nl/software/code/haskell/lists.md b/portfolio/pages/nl/software/code/haskell/lists.md new file mode 100644 index 0000000..f095176 --- /dev/null +++ b/portfolio/pages/nl/software/code/haskell/lists.md @@ -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] +``` + diff --git a/portfolio/pages/nl/software/code/haskell/pattern-matching.md b/portfolio/pages/nl/software/code/haskell/pattern-matching.md new file mode 100644 index 0000000..b5b6b5f --- /dev/null +++ b/portfolio/pages/nl/software/code/haskell/pattern-matching.md @@ -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 +``` + diff --git a/portfolio/pages/nl/software/code/haskell/recursive-functions.md b/portfolio/pages/nl/software/code/haskell/recursive-functions.md new file mode 100644 index 0000000..398e438 --- /dev/null +++ b/portfolio/pages/nl/software/code/haskell/recursive-functions.md @@ -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)) +``` + diff --git a/portfolio/pages/nl/software/code/haskell/strings.md b/portfolio/pages/nl/software/code/haskell/strings.md new file mode 100644 index 0000000..64a3cf9 --- /dev/null +++ b/portfolio/pages/nl/software/code/haskell/strings.md @@ -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 +```