From f8586974b670ae4b7f07c65f1b2c7715c0c322b4 Mon Sep 17 00:00:00 2001 From: "Yann Esposito (Yogsototh)" Date: Wed, 1 Jan 2020 23:54:53 +0100 Subject: [PATCH] first pass --- src/css/mk.css | 2 +- src/posts/0010-Haskell-Now/hspwg.init.tar.gz | Bin 0 -> 2724 bytes src/posts/0010-Haskell-Now/hspwg/.envrc | 1 + src/posts/0010-Haskell-Now/hspwg/.gitignore | 2 + src/posts/0010-Haskell-Now/hspwg/CHANGELOG.md | 5 ++ src/posts/0010-Haskell-Now/hspwg/LICENSE | 30 +++++++++ src/posts/0010-Haskell-Now/hspwg/Setup.hs | 2 + src/posts/0010-Haskell-Now/hspwg/app/Main.hs | 12 ++++ src/posts/0010-Haskell-Now/hspwg/default.nix | 35 +++++++++++ src/posts/0010-Haskell-Now/hspwg/hspwg.cabal | 58 ++++++++++++++++++ src/posts/0010-Haskell-Now/hspwg/nixpkgs.nix | 1 + src/posts/0010-Haskell-Now/hspwg/release.nix | 4 ++ src/posts/0010-Haskell-Now/hspwg/shell.nix | 1 + src/posts/0010-Haskell-Now/hspwg/src/MyLib.hs | 15 +++++ .../0010-Haskell-Now/hspwg/test/MyLibTest.hs | 4 ++ src/posts/0010-Haskell-Now/index.org | 53 +++++++++++----- 16 files changed, 207 insertions(+), 18 deletions(-) create mode 100644 src/posts/0010-Haskell-Now/hspwg.init.tar.gz create mode 100644 src/posts/0010-Haskell-Now/hspwg/.envrc create mode 100644 src/posts/0010-Haskell-Now/hspwg/.gitignore create mode 100644 src/posts/0010-Haskell-Now/hspwg/CHANGELOG.md create mode 100644 src/posts/0010-Haskell-Now/hspwg/LICENSE create mode 100644 src/posts/0010-Haskell-Now/hspwg/Setup.hs create mode 100644 src/posts/0010-Haskell-Now/hspwg/app/Main.hs create mode 100644 src/posts/0010-Haskell-Now/hspwg/default.nix create mode 100644 src/posts/0010-Haskell-Now/hspwg/hspwg.cabal create mode 100644 src/posts/0010-Haskell-Now/hspwg/nixpkgs.nix create mode 100644 src/posts/0010-Haskell-Now/hspwg/release.nix create mode 100644 src/posts/0010-Haskell-Now/hspwg/shell.nix create mode 100644 src/posts/0010-Haskell-Now/hspwg/src/MyLib.hs create mode 100644 src/posts/0010-Haskell-Now/hspwg/test/MyLibTest.hs diff --git a/src/css/mk.css b/src/css/mk.css index 50c32ba..a82509c 100644 --- a/src/css/mk.css +++ b/src/css/mk.css @@ -217,7 +217,7 @@ figure, .figure { content: ": "; } .notes { - padding: 5px 10px; + padding: 1ex; } .underline { text-decoration: underline; diff --git a/src/posts/0010-Haskell-Now/hspwg.init.tar.gz b/src/posts/0010-Haskell-Now/hspwg.init.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..a7d61b55ebeba1e249f463415b1479dceb65b64d GIT binary patch literal 2724 zcmV;V3S0FbiwFoU8Vz0m188$_cV{kiVR8WN8*6jhxG|skE4EH&Y~P5~%a1vEa;+@U zHfLnX73sL1)^AZ))}WVWaj2_Sef+2C0xf2Y560iAb2B zFSWyFT ze>zJTm#{M?GMIWkANf%PQz;YCs#YgdPScSUuvxWF?*?vRCsm&ZQ+h+H^`EWU&lU>M zn*4hg?mrvfdN?I~C1n2Z5}78}RIG=_YyMx`KUnyGbMFBCzu7$4EB${Hko$j^3d!jx zm6XMni-i#}WyoQ~ah z?KRPO#s8bQ-&>vk51WnB|2F|0mdrVwOmPbs>_Vf~s8!(Fk7Ka4G$ezaYc>%~GC4)Z zZ{zMzHy6N(ApC}emSGG@xD-EvABT_%0yrxOmhyn;k`ax4K8G>mGf{zC+*$(T`j@5B zzm^Q*;*vB9PH>oEirg)j$yr#i^!3c-7#>)He6S%4(iw@RUns1Kxl|KT58Q`+KU0l8GgnEvNMMfQTBvm zV?g2%ONlZaWN*eKflO{_ksl1!`Jq)({sFQP4C3<`ij=cU}&`AqCNDS&SkGXgp14J z#lW>e4Xf+8onG5Hx4RZnM~Yy-xBDKrXYF3^@hFYKRo@;e)|ZC}$2Rnw_HoZvg!CZ0 z&d~07YBUc|9TXh0*Q*%rh23%R0cBz1SlYwuN{-XD|8|LuuoAlM^Y$qYZRZtE*725`Aw3kJXFQA%`u1thIko#8Th$H}mMh1#cTrW2s~R|(EGi#qUg{w$6(LuK zeq1uxidG~zC(!P`cNE)sV^qECi_#s&j0rJYNh{g0^Z{0^oFWE z58ze_cU*c;3fe3TJpWuXYoB?hK*Bd586A@o+()4~3 z(paQwne|i7A5!lI3`>m=4_n&ty zZ3(5P{xFdFKhGxbZWZ~h=@Ar4#^mU`$tp3kwIev?qN3nXTsTU zxRPhNAl5^{5tIpEe{{(F-9W=gT{m=7%oBI5x^#ApPy2~+Rax3IKB2|ME zkw&ug>K_I&|Ic&$zRmhyKd7z7|9iEA(*HLC_mJmw!(SfO|E13Xj0yy7me7cBY_XLa z$`%%f?3l#CbmsFlJiKk}mnjwu_)QlxZ`{T_!({6^u@`>AKJ>GBiC;a;=z7A7Pn+?NEVj7=ha zLvIwf?q^xiJCHmjN4hv!l2!{oAhlnQa!iY=kR&7yao7}Jc1H6em3NhyUEOh%(kOJ| zB$W!OzU+TS1qwdEG@`Lw$Z;|aXt;O_l#EOoqr>1%@=>Xh+@fSk6>kq%-r_%0>zt)< ztCTDm_+bbtTMWcpNHPOd5&r)~AP!P4hyzE{Tax%IKu zY<{R8H5;>!zka;>_(8wd@a5NEKxM;iZ!5BBKHoBm&gOsp*U~y#1C3Ya|HeV%;rpNc zgKYlaFY`Y)0-3kwr?{=$NgCFkVVdB?=tO>0Oei>gh=9{XrwnZ`nauWL^3uMytqXAp zpmN(%c+@mEPPtAGdX#un0YQlV+Nf2n7PB?uld8s0O$D-LPEs0TWNIjM9aBhgj3Jb?>*KC@d z$VXm_7UmdN%SE$1wbJlYIc0oh0550SsrxpSnnsqp%(1ye^5%b?V4FyNoTXS@B#E_* z02MJ|eEx`*OK`@ca&C}2$$c|RgwvcV!7ShZ7zU!8p^9-H921=mg%*M@3E`6JIWu2J z%*c-?DOyIW$ntH}>NO)@O3ZBe5!u{3@^PL0$1m^pta?MMMK2pB)56Z%m{-M$VP2`A z!XJQjH^Ct(_gxMY|CqQcRk?A%%rILt>Sym&bocKjj;g+f53={neyNh>bf9oYV6vKK}27ZzlhRR_uvkPh6 z*i;2yBnUZAp3W@fj!Km$Y6=-rX4bXIK1)5P^Sn5haw;Qe;( literal 0 HcmV?d00001 diff --git a/src/posts/0010-Haskell-Now/hspwg/.envrc b/src/posts/0010-Haskell-Now/hspwg/.envrc new file mode 100644 index 0000000..1d953f4 --- /dev/null +++ b/src/posts/0010-Haskell-Now/hspwg/.envrc @@ -0,0 +1 @@ +use nix diff --git a/src/posts/0010-Haskell-Now/hspwg/.gitignore b/src/posts/0010-Haskell-Now/hspwg/.gitignore new file mode 100644 index 0000000..6d7e2df --- /dev/null +++ b/src/posts/0010-Haskell-Now/hspwg/.gitignore @@ -0,0 +1,2 @@ +dist-newstyle/ +result diff --git a/src/posts/0010-Haskell-Now/hspwg/CHANGELOG.md b/src/posts/0010-Haskell-Now/hspwg/CHANGELOG.md new file mode 100644 index 0000000..62981e2 --- /dev/null +++ b/src/posts/0010-Haskell-Now/hspwg/CHANGELOG.md @@ -0,0 +1,5 @@ +# Revision history for hspwg + +## 0.1.0.0 -- YYYY-mm-dd + +* First version. Released on an unsuspecting world. diff --git a/src/posts/0010-Haskell-Now/hspwg/LICENSE b/src/posts/0010-Haskell-Now/hspwg/LICENSE new file mode 100644 index 0000000..59ef795 --- /dev/null +++ b/src/posts/0010-Haskell-Now/hspwg/LICENSE @@ -0,0 +1,30 @@ +Copyright (c) 2020, Yann Esposito (Yogsototh) + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of Yann Esposito (Yogsototh) nor the names of other + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/posts/0010-Haskell-Now/hspwg/Setup.hs b/src/posts/0010-Haskell-Now/hspwg/Setup.hs new file mode 100644 index 0000000..9a994af --- /dev/null +++ b/src/posts/0010-Haskell-Now/hspwg/Setup.hs @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain diff --git a/src/posts/0010-Haskell-Now/hspwg/app/Main.hs b/src/posts/0010-Haskell-Now/hspwg/app/Main.hs new file mode 100644 index 0000000..4a932cc --- /dev/null +++ b/src/posts/0010-Haskell-Now/hspwg/app/Main.hs @@ -0,0 +1,12 @@ +{-# LANGUAGE NoImplicitPrelude #-} +{-# LANGUAGE OverloadedStrings #-} +module Main where + +import Protolude + +import qualified MyLib (genPassword) + +main :: IO () +main = do + pwd <- MyLib.genPassword + putText pwd diff --git a/src/posts/0010-Haskell-Now/hspwg/default.nix b/src/posts/0010-Haskell-Now/hspwg/default.nix new file mode 100644 index 0000000..40f3806 --- /dev/null +++ b/src/posts/0010-Haskell-Now/hspwg/default.nix @@ -0,0 +1,35 @@ +{ nixpkgs ? import ./nixpkgs.nix +, compiler ? "default" +, doBenchmark ? false }: +let + inherit (nixpkgs) pkgs; + name = "hspwg"; + haskellPackages = pkgs.haskellPackages; + variant = if doBenchmark + then pkgs.haskell.lib.doBenchmark + else pkgs.lib.id; + drv = haskellPackages.callCabal2nix name ./. {}; +in +{ + my_project = drv; + shell = haskellPackages.shellFor { + # generate hoogle doc + withHoogle = true; + packages = p: [drv]; + # packages dependencies (by default haskellPackages) + buildInputs = with haskellPackages; + [ hlint + ghcid + cabal-install + cabal2nix + hindent + # # if you want to add some system lib like ncurses + # # you could by writing it like: + # pkgs.ncurses + ]; + # nice prompt for the nix-shell + shellHook = '' + export PS1="\n[${name}:\033[1;32m\]\W\[\033[0m\]]> " + ''; + }; +} diff --git a/src/posts/0010-Haskell-Now/hspwg/hspwg.cabal b/src/posts/0010-Haskell-Now/hspwg/hspwg.cabal new file mode 100644 index 0000000..8f43f4f --- /dev/null +++ b/src/posts/0010-Haskell-Now/hspwg/hspwg.cabal @@ -0,0 +1,58 @@ +cabal-version: 2.4 +-- Initial package description 'hspwg.cabal' generated by 'cabal init'. +-- For further documentation, see http://haskell.org/cabal/users-guide/ + +name: hspwg +version: 0.1.0.0 +synopsis: Password Generator +-- description: +-- bug-reports: +license: BSD-3-Clause +license-file: LICENSE +author: Yann Esposito (Yogsototh) +maintainer: yann.esposito@gmail.com +-- copyright: +category: Security +extra-source-files: CHANGELOG.md + +common professional-properties + default-language: Haskell2010 + build-depends: + base ^>=4.12.0.0 + ghc-options: + -Wall + -Wcompat + -Wincomplete-uni-patterns + -Wredundant-constraints + -Wnoncanonical-monad-instances + -- -Werror + -- -O2 + +library + import: professional-properties + exposed-modules: MyLib + -- other-modules: + -- other-extensions: + build-depends: protolude, + random + hs-source-dirs: src + +executable hspwg + import: professional-properties + main-is: Main.hs + -- other-modules: + -- other-extensions: + ghc-options: + -- enable parallelism + -threaded + "-with-rtsopts=-N" + build-depends: hspwg, + protolude + hs-source-dirs: app + +test-suite hspwg-test + import: professional-properties + type: exitcode-stdio-1.0 + hs-source-dirs: test + main-is: MyLibTest.hs + -- build-depends: base ^>=4.12.0.0 diff --git a/src/posts/0010-Haskell-Now/hspwg/nixpkgs.nix b/src/posts/0010-Haskell-Now/hspwg/nixpkgs.nix new file mode 100644 index 0000000..aae2b1d --- /dev/null +++ b/src/posts/0010-Haskell-Now/hspwg/nixpkgs.nix @@ -0,0 +1 @@ +import (fetchTarball https://github.com/NixOS/nixpkgs/archive/19.09.tar.gz) {} diff --git a/src/posts/0010-Haskell-Now/hspwg/release.nix b/src/posts/0010-Haskell-Now/hspwg/release.nix new file mode 100644 index 0000000..8a1ee52 --- /dev/null +++ b/src/posts/0010-Haskell-Now/hspwg/release.nix @@ -0,0 +1,4 @@ +let + def = import ./. {}; +in + { my_project = def.my_project; } diff --git a/src/posts/0010-Haskell-Now/hspwg/shell.nix b/src/posts/0010-Haskell-Now/hspwg/shell.nix new file mode 100644 index 0000000..0d9af5e --- /dev/null +++ b/src/posts/0010-Haskell-Now/hspwg/shell.nix @@ -0,0 +1 @@ +(import ./. {}).shell diff --git a/src/posts/0010-Haskell-Now/hspwg/src/MyLib.hs b/src/posts/0010-Haskell-Now/hspwg/src/MyLib.hs new file mode 100644 index 0000000..1555d91 --- /dev/null +++ b/src/posts/0010-Haskell-Now/hspwg/src/MyLib.hs @@ -0,0 +1,15 @@ +{-# LANGUAGE NoImplicitPrelude #-} +{-# LANGUAGE OverloadedStrings #-} +module MyLib (genPassword) where + +import Protolude + +import Data.Char (chr,ord) +import qualified System.Random as Random + +genPassword :: IO Text +genPassword = do + let stdgen = Random.mkStdGen 0 + numbers = take 10 (Random.randoms stdgen) + password = toS [ chr ( (n `mod` 27) + ord 'a') | n <- numbers ] + return password diff --git a/src/posts/0010-Haskell-Now/hspwg/test/MyLibTest.hs b/src/posts/0010-Haskell-Now/hspwg/test/MyLibTest.hs new file mode 100644 index 0000000..3e2059e --- /dev/null +++ b/src/posts/0010-Haskell-Now/hspwg/test/MyLibTest.hs @@ -0,0 +1,4 @@ +module Main (main) where + +main :: IO () +main = putStrLn "Test suite not yet implemented." diff --git a/src/posts/0010-Haskell-Now/index.org b/src/posts/0010-Haskell-Now/index.org index 70b61df..317ab29 100644 --- a/src/posts/0010-Haskell-Now/index.org +++ b/src/posts/0010-Haskell-Now/index.org @@ -162,7 +162,7 @@ The article contains five parts: - More on infinite tree; a more math oriented discussion about infinite trees -** Helpers :noexport: +** Helpers :noexport: :PROPERTIES: :CUSTOM_ID: helpers :END: @@ -177,9 +177,10 @@ The article contains five parts: #+CAPTION: Haskell logo [[./Haskell-logo.png]] -1. Install [[https://nixos.org/nix][nix]] -2. create a new empty directory =hsenv= somewhere -3. Put the following =shell.nix= file inside it +1. Install [[https://nixos.org/nix][nix]] (The version I use is nix (Nix) 2.3.1, future 2.X.X versions + should work with the examples in this article) +3. create a new empty directory =hsenv= somewhere +4. Put the following =shell.nix= file inside it {{{lnk(shell.nix)}}} #+begin_src nix :tangle shell.nix @@ -211,7 +212,7 @@ The article contains five parts: } #+end_src -4. In the =hsenv= directory, in a terminal, run =nix-shell --pure=. +5. In the =hsenv= directory, in a terminal, run =nix-shell --pure=. You should wait a lot of time for everything to download. And you should be ready. You will have in your PATH: @@ -220,7 +221,7 @@ The article contains five parts: - =runghc= that will be able to interpret a Haskell file - =cabal= which is the main tool to deal with Haskell projects - the Haskell libraries =protolude= and =containers=. -5. To test your env, rung =ghci= and type =import Protolude= you should see +6. To test your env, rung =ghci= and type =import Protolude= you should see something like this: #+begin_src @@ -3494,18 +3495,17 @@ it really "clicked" for them. :CUSTOM_ID: start-a-new-project :END: -There are many different way to start. +There are multiple starting options to create a new project. The most common one is certainly to use =cabal-install=. Another popular option is to use =stack=. -=stack= add a layer on top of =cabal-install= and use fixed set of libraries -known to compile together. -The last option is to use =cabal-install= but take care of the dependencies -of your project via =nix=. - -The last option is often considered as the most complex and difficult for -beginner. -And guess what? -Against all odds, I will introduce haskell project development via =nix=. +=stack= adds a layer on top of =cabal-install= and uses fixed set of +libraries known to compile together. +Another method is to =nix= to handle the dependencies and use +=cabal-install= for the rest. +That final choice is often considered as the most complex and difficult for +beginners. +Still this is the one I find the most elegant. +This is the method I will use in this article. Still, you shall not be intimidated. Look: @@ -3943,7 +3943,7 @@ executable my-app #+end_src #+begin_notes -I did not included a version constraint here. +I did not include a version constraint here. This is ok if you do not deploy your library publicly. This would be absolutely awful if you deploy your library publicly. So while developing a private app nobody can see except you, nothing is @@ -4081,6 +4081,25 @@ You can download the final cabal file: [[file:my-app/my-app.cabal][my-app.cabal] :CUSTOM_ID: command-line-application :END: +One of the simplest while still useful command line utility I can think of +is a simple strong password generator. + +*** Password Generator +:PROPERTIES: +:CUSTOM_ID: password-generator +:END: + +Create a new project named =hspwg= (HaSkell PassWord Generator). +If you do not want to go through the process of creating a new project form +scratch again you can download an archive here: [[file:hspwg.init.tar.gz]]. + +Let us write the most basic application possible. +Edit the file =src/Main.hs= with: + +#+begin_src haskell + +#+end_src + ** Web Application :PROPERTIES: :CUSTOM_ID: web-application