first pass
This commit is contained in:
parent
e24de08c34
commit
f8586974b6
16 changed files with 207 additions and 18 deletions
|
@ -217,7 +217,7 @@ figure, .figure {
|
||||||
content: ": ";
|
content: ": ";
|
||||||
}
|
}
|
||||||
.notes {
|
.notes {
|
||||||
padding: 5px 10px;
|
padding: 1ex;
|
||||||
}
|
}
|
||||||
.underline {
|
.underline {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
|
|
BIN
src/posts/0010-Haskell-Now/hspwg.init.tar.gz
Normal file
BIN
src/posts/0010-Haskell-Now/hspwg.init.tar.gz
Normal file
Binary file not shown.
1
src/posts/0010-Haskell-Now/hspwg/.envrc
Normal file
1
src/posts/0010-Haskell-Now/hspwg/.envrc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
use nix
|
2
src/posts/0010-Haskell-Now/hspwg/.gitignore
vendored
Normal file
2
src/posts/0010-Haskell-Now/hspwg/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
dist-newstyle/
|
||||||
|
result
|
5
src/posts/0010-Haskell-Now/hspwg/CHANGELOG.md
Normal file
5
src/posts/0010-Haskell-Now/hspwg/CHANGELOG.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# Revision history for hspwg
|
||||||
|
|
||||||
|
## 0.1.0.0 -- YYYY-mm-dd
|
||||||
|
|
||||||
|
* First version. Released on an unsuspecting world.
|
30
src/posts/0010-Haskell-Now/hspwg/LICENSE
Normal file
30
src/posts/0010-Haskell-Now/hspwg/LICENSE
Normal file
|
@ -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.
|
2
src/posts/0010-Haskell-Now/hspwg/Setup.hs
Normal file
2
src/posts/0010-Haskell-Now/hspwg/Setup.hs
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
import Distribution.Simple
|
||||||
|
main = defaultMain
|
12
src/posts/0010-Haskell-Now/hspwg/app/Main.hs
Normal file
12
src/posts/0010-Haskell-Now/hspwg/app/Main.hs
Normal file
|
@ -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
|
35
src/posts/0010-Haskell-Now/hspwg/default.nix
Normal file
35
src/posts/0010-Haskell-Now/hspwg/default.nix
Normal file
|
@ -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\]]> "
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
58
src/posts/0010-Haskell-Now/hspwg/hspwg.cabal
Normal file
58
src/posts/0010-Haskell-Now/hspwg/hspwg.cabal
Normal file
|
@ -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
|
1
src/posts/0010-Haskell-Now/hspwg/nixpkgs.nix
Normal file
1
src/posts/0010-Haskell-Now/hspwg/nixpkgs.nix
Normal file
|
@ -0,0 +1 @@
|
||||||
|
import (fetchTarball https://github.com/NixOS/nixpkgs/archive/19.09.tar.gz) {}
|
4
src/posts/0010-Haskell-Now/hspwg/release.nix
Normal file
4
src/posts/0010-Haskell-Now/hspwg/release.nix
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
let
|
||||||
|
def = import ./. {};
|
||||||
|
in
|
||||||
|
{ my_project = def.my_project; }
|
1
src/posts/0010-Haskell-Now/hspwg/shell.nix
Normal file
1
src/posts/0010-Haskell-Now/hspwg/shell.nix
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(import ./. {}).shell
|
15
src/posts/0010-Haskell-Now/hspwg/src/MyLib.hs
Normal file
15
src/posts/0010-Haskell-Now/hspwg/src/MyLib.hs
Normal file
|
@ -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
|
4
src/posts/0010-Haskell-Now/hspwg/test/MyLibTest.hs
Normal file
4
src/posts/0010-Haskell-Now/hspwg/test/MyLibTest.hs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
module Main (main) where
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = putStrLn "Test suite not yet implemented."
|
|
@ -177,9 +177,10 @@ The article contains five parts:
|
||||||
#+CAPTION: Haskell logo
|
#+CAPTION: Haskell logo
|
||||||
[[./Haskell-logo.png]]
|
[[./Haskell-logo.png]]
|
||||||
|
|
||||||
1. Install [[https://nixos.org/nix][nix]]
|
1. Install [[https://nixos.org/nix][nix]] (The version I use is nix (Nix) 2.3.1, future 2.X.X versions
|
||||||
2. create a new empty directory =hsenv= somewhere
|
should work with the examples in this article)
|
||||||
3. Put the following =shell.nix= file inside it
|
3. create a new empty directory =hsenv= somewhere
|
||||||
|
4. Put the following =shell.nix= file inside it
|
||||||
|
|
||||||
{{{lnk(shell.nix)}}}
|
{{{lnk(shell.nix)}}}
|
||||||
#+begin_src nix :tangle shell.nix
|
#+begin_src nix :tangle shell.nix
|
||||||
|
@ -211,7 +212,7 @@ The article contains five parts:
|
||||||
}
|
}
|
||||||
#+end_src
|
#+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.
|
You should wait a lot of time for everything to download.
|
||||||
And you should be ready.
|
And you should be ready.
|
||||||
You will have in your PATH:
|
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
|
- =runghc= that will be able to interpret a Haskell file
|
||||||
- =cabal= which is the main tool to deal with Haskell projects
|
- =cabal= which is the main tool to deal with Haskell projects
|
||||||
- the Haskell libraries =protolude= and =containers=.
|
- 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:
|
something like this:
|
||||||
|
|
||||||
#+begin_src
|
#+begin_src
|
||||||
|
@ -3494,18 +3495,17 @@ it really "clicked" for them.
|
||||||
:CUSTOM_ID: start-a-new-project
|
:CUSTOM_ID: start-a-new-project
|
||||||
:END:
|
: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=.
|
The most common one is certainly to use =cabal-install=.
|
||||||
Another popular option is to use =stack=.
|
Another popular option is to use =stack=.
|
||||||
=stack= add a layer on top of =cabal-install= and use fixed set of libraries
|
=stack= adds a layer on top of =cabal-install= and uses fixed set of
|
||||||
known to compile together.
|
libraries known to compile together.
|
||||||
The last option is to use =cabal-install= but take care of the dependencies
|
Another method is to =nix= to handle the dependencies and use
|
||||||
of your project via =nix=.
|
=cabal-install= for the rest.
|
||||||
|
That final choice is often considered as the most complex and difficult for
|
||||||
The last option is often considered as the most complex and difficult for
|
beginners.
|
||||||
beginner.
|
Still this is the one I find the most elegant.
|
||||||
And guess what?
|
This is the method I will use in this article.
|
||||||
Against all odds, I will introduce haskell project development via =nix=.
|
|
||||||
|
|
||||||
Still, you shall not be intimidated. Look:
|
Still, you shall not be intimidated. Look:
|
||||||
|
|
||||||
|
@ -3943,7 +3943,7 @@ executable my-app
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
#+begin_notes
|
#+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 is ok if you do not deploy your library publicly.
|
||||||
This would be absolutely awful if you 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
|
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
|
:CUSTOM_ID: command-line-application
|
||||||
:END:
|
: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
|
** Web Application
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:CUSTOM_ID: web-application
|
:CUSTOM_ID: web-application
|
||||||
|
|
Loading…
Reference in a new issue