first pass
This commit is contained in:
parent
e24de08c34
commit
f8586974b6
|
@ -217,7 +217,7 @@ figure, .figure {
|
|||
content: ": ";
|
||||
}
|
||||
.notes {
|
||||
padding: 5px 10px;
|
||||
padding: 1ex;
|
||||
}
|
||||
.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
|
||||
[[./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
|
||||
|
|
Loading…
Reference in a new issue