Deploying React to GitHub Pages

  • Create a new repository on GitHub, so we have something to refer to mine’s called react.io so simply replace this with your repo name within these steps, also the steps will show my GitHub repository at putridparrot, again replace this with your GitHub username.
  • Clone the repository onto your local machine
  • In the parent folder of your cloned repository run
    yarn create react-app react.io --typescript
    

    Note: without –typescript if you want plain JavaScript code.

  • cd back into your repo folder and type
    yarn add gh-pages -D
    
  • Open your packages.json and add the following (below the “verson” is a good place)
    "homepage": "http://putridparrot.github.io/react.io",
    
  • Next up we need to add a predeploy and deploy script within the “scripts” section of the packages.json, so add these
    "deploy": "gh-pages -d build",
    "predeploy": "yarn run build"
    
  • Run the following from your shell/terminal
    yarn deploy
    

When we run yarn deploy the predeploy script is run and will create a gh-pages branch on your GitHub remote repo. Also it will default to this branch and when you go to the Settings page of your repository and scroll to the GithHub Pages section, you should see the source set to gh-pages branch.

As this point my React GitHub pages site should be visible at

https://putridparrot.github.io/react.io/

You may well want to push the source of your React application to GitHub as well, so simply commit and push to master or another branch, DO NOT overwrite the gh-pages branch, this is basically your deployed site.

To update your GitHub pages, simply run the following each time you’re ready to deploy to gh-pages

yarn deploy

The updated deployment may take up to ten minute to become available.

Creating types in Haskell

In most programming language we need ways to declare our own types. These help with readability, modularity etc. Haskell is no different in offering these capabilities.

We can create a simple data type using the data keyword, followed by either of available values (in C# this would be similar to an enum). So here’s the definition of a Boolean type

data Bool = False | True

The values after the = are the value constructors with the | being like an or, hence this Bool have either False or True value.

Note: The type name and the value constructor must be capital cased.

We can also declare types more like structs/classes in that we can define the field types that make up the type. For example here’s a Point type

data Point = Point Integer Integer

In this example we could create a point as follows

pt = Point 1 2

Accessing these values can be a little verbose (especially when we might have lots of fields) because of the lack of any names, hence we’d use pattern matching, i.e.

xpt :: Point -> Integer
xpt (Point x _) = x

-- example of printing the x value of value pt of type Point
print (xpt pt)

Note: The type annotation is not required and the underscore is a discard, hence is ignored.

We can combine types just as we combined False and True into essentially a union. So for example here we have a data type Shape with constructors for Circle and Triangle.

data Shape = Triangle Int Int Int | Circle Int

triangle = Triangle 1 2 3
circle = Circle 4

It’s not clear what these fields of the constructors mean, so let’s add some names which also allows us to more easily access specific values from the data (i.e. fixes the issue with using pattern matching – which ofcourse is still a valid way of doing things).

data Shape = Triangle { 
   hypotenuse :: Int, 
   opposite :: Int, 
   adjacent :: Int 
} | Circle { 
  radius :: Int 
}

We can declare instances of this type using names or without names, for example

-- not using names
triangle = Triangle 1 2 3
-- with names
triangle1 = Triangle { opposite = 5, hypotenuse = 6, adjacent = 7 }

Instead of creating a function to extract a value (like we did with the xpt function we created) we can now use the following

print (hypotenuse triangle)

and Haskell essentially creates the function for us, i.e. using the REPL along with :t hypotenuse we get the following

hypotenuse :: Shape -> Int

Haskell is immutable, so how do we make changes to an instance of data? Well we “copy and update”. Thankfully Haskell makes this easy (so we don’t have to literally create copies of every field on our data and then change values).

If you’ve used JavaScript it’s like using a spread operator of in F# and with.

newTriangle = triangle { hypotenuse = 10 } 

In this case newTriangle is a copy of the triangle data, with the hypotenuse changed.

Unit testing Haskel code with HUnit

As with most languages nowadays, we want to have some unit testing libraries/frameworks. Obviously Haskell is no different and we have tools such as HUnit.

Let’s first create a simple little bit of code to test, here’s my Calculator.hs file (abridged just to show the code I intend to write tests for)

module Modules.Calculator where

factorial :: (Integral a) => a -> a  
factorial 0 = 1  
factorial n = n * factorial (n - 1) 

We’ll need to have installed the HUnit package, if you haven’t already then run

cabal install --lib QuickCheck HUnit

We’ll store our tests in a folder named test off of our root folder (the name of the folder can be altered if you prefer).

Here’s our test code (my file is named CalculatorTests.hs)

module Main (main) where

import Test.HUnit
import System.Exit

import Modules.Calculator as Calc

testZeroCase = TestCase(assertEqual "Factorial 1" (1) (Calc.factorial 1))
testNonZeroCase = TestCase(assertEqual "Factorial 10" (2) (Calc.factorial 10))

main :: IO ()
main = do
    counts <- runTestTT ( test [
        testZeroCase,
        testNonZeroCase
        ])
    if (errors counts + failures counts == 0)
        then exitSuccess
        else exitFailure

In the above code we import our library code and have two tests, the first tests our factorial code with a 0 value, the second tests a non-zero. In this instance I’ve purposefully written a breaking test.

Before we run these and/or fix the tests let’s see what we’re doing with the test code. We create a function for the TestCase and within the TestCase we have our assertion along with a message prefix (the string), next we have the expected value and finally the actual value or in this case the function call which returns the actual value.

In main we basically create the test runner and supply an array of the test functions to be run, finally we exit the runner with success or failure.

Now before we can run our tests we need to declare a Test-Suite within the .cabal file. We add the following to the file

Test-Suite test-Calculator
  type:                exitcode-stdio-1.0
  hs-source-dirs:      test
                       .
  default-language:    Haskell2010
  main-is:             CalculatorTests.hs
  other-modules:       Modules.Calculator
  build-depends:       base >=4.14 && <4.15, HUnit

This tells cabal the folder to look for the tests (test in this case) along with . for the current folder (otherwise our tests won’t find out Calculator module). We then state what the main application for the cabal to run for the tests, include other modules etc.

Now run

cabal test

If all goes well you’ll get something like the following

Running 1 test suites...
Test suite test-Calculator: RUNNING...
### Failure in: 1
test\CalculatorTests.hs:9
Factorial 10
expected: 2
 but got: 3628800
Cases: 2  Tried: 2  Errors: 0  Failures: 1
Test suite test-Calculator: FAIL
Test suite logged to:
D:\Development\somefolder\test\HaskellBasics-0.1.0.0-test-HaskellBasics.log
0 of 1 test suites (0 of 1 test cases) passed.
cabal.exe: Tests failed for test:test-Calculator from
Calculator-0.1.0.0.

Obviously the test with the prefix message “Factorial 10” failed with the expected value 2 but the actual value 3628800, so we can fix that test case so it looks like this

testNonZeroCase = TestCase(assertEqual "Factorial 10" (3628800) (Calc.factorial 10))

and now all our tests will pass.

I’ll leave it to the reader to look into the other assertions etc. For example, checkout Test.HUnit.Base

Other References

HUnit: A unit testing framework for Haskell

Getting Started with Cabal

Cabal is the Haskell package and build tool.

The following are a few of the “getting started” commands.

What version do you have of Cabal?

Run the following

cabal --version

Check for updates to Cabal

You can check

cabal new-install Cabal cabal-install

Check for package updates

This command will pull the latest package list from hackage.haskell.org

cabal update

Creating a new project

We can create a new Haskell project using

cabal init

This will create a Main.hs, Setup.hs and a .cabal file for your configurations. We can then edit the .cabal file or we can run the interactive version and supply details using

cabal init -i

Building our project

We can build our project by simply using

cabal build

Running our project

To run (or build and run)

cabal run

Cleaning our project

cabal clean

Running the ghci repl

You can run ghci by simply typing

ghci

Or you can run the ghci that’s available via cabal using

cabal repl

Adding a library

We can download and install package from The Haskell Package Repository using the command

cabal install --lib QuickCheck HUnit

This installs the packages QuickCheck and HUnit from the package repository. The –lib is used for packages which do not contain an executable (i.e. a library package). We can also install .gz packages by specifying a file location or URL.

Packages are then stored on Windows in

%USERPROFILE%\AppData\Roaming\cabal\store\ghc-8.10.1

References

Welcome to the Cabal User Guide

The Haskell repl – basic commands

Haskell’s repl can be run use ghci or cabal repl. The repl using : to prefix commands, so for example :? will list the help.

I’m not going to go through all commands, but just the one’s I’ve been using regularly, check out Cabal for the full list of commands and features.

Quitting the repl

Let’s start by looking at how to quitting the repl (gracefully)

Prelude> :q

Writing code

Obviously we want to be able to execute code in the repl, in such cases we write code such as

x = 1 + 2
-- press enter
x
-- press enter

The output from this will obviously be 3.

To handle multi line input we create a block using :{ and :}, for example

:{
data Expr = Lit Integer |
            Div Expr Expr
:}

Don’t forget indention is required!

Loading existing code

In some cases we might want to load existing code into the repl, such a data definitions etc. Let’s say we have a Main.hs then run

:load Main

Display information

Assuming we added the Expr data type, to the repl, we might want to show the definition at some point, just use

:i Expr

Showing the type of an expression

Let’s assume we have something like the following in a module

eval :: Expr -> Integer

We can use the following to return the type (obviously in this instance we should see the above, but this command can ofcourse be executed against types where we want to find the type annotations/decalaractions

:t Expr

Now try

:t print

and you’ll see the following

print :: Show a => a -> IO ()

References

Using GHCi
Cabal User Guide

How to yarn link when the package is not published?

In the previous post we looked at using yarn link to work on development of a package whilst using it within our application (or other package).

There’s a problem. This only works if you’ve previously published the package to an npm compatible repository because when you run yarn in your application, it’ll see the dependency of your package and try to get it from the remote repository.

Note: this in not an issue if the package was published it’s only an issue for unpublished packages.

What we can do is change the dependency from using a version number to essentially use a local path. For example, let’s assume we have the following in our packages.json

"dependencies": {
   "@namespace/package-name": "1.0.0"
}

As stated, running yarn will result in and error no such package available. Changing this line to

"dependencies": {
   "@namespace/package-name": "link:../dev/package-name"
}

In other words, link: followed by the path to our package under development, then all will work, running yarn will no longer fail with the no such package available error.

You also needn’t run the link commands on the package or application to create a symbolic link if you use this syntax, just remember to change it back to the version number once the package is published.

yarn link

Yarn’s link functionality is really useful when developing a package and wanting to use it in your application whilst the package is in development.

Let’s assume you’ve created a package, for the sake of having an example, let’s assume it’s a cool new radio button control. You’ve created it and pushed to npm and all’s great but then you want to make some changes.

You don’t want to make those changes and push them to npm so that you can test them, yes you could take the code from the package etc. or use Yalc.

Or we can use yarn link.

In the package you’re editing, simply run

yarn link

this will result in the following command being available to run in the application using the package

yarn link "@namespace/package-name"

Note: obviously remove the namespace if non is used and replace package-name with the name of the package to link.

After you execute the above command and if you’re using Visual Code’s look at the explorer window, in the node_modules of the application using the package you’ll find the @namespace/package-name with a little symbolic link icon.

If you wish to unlink then, from your application use

yarn unlink "@namespace/package-name"

and from the package itself

yarn ulink

Haskell basics – Modules

Note: I’ve writing these Haskell blog posts whilst learning Haskell, so do not take them as expert guidance. I will amend the post(s) as I learn more.

Before we begin, let’s use cabal init to create a starter project, then we’ll add our code to this project as part of this post. This will create a Main.hs with the classic “Hello World” type of sample along with the Setup.hs and the .cabal file.

Modules

Apart from the simplest applications we would probably want to package functions, types etc. into modules. Modules exist in most languages, such as those in F#, TypeScript or similar to namespaces in C# & Java. In Haskell each module is stored within it’s own file and the file begins with the following declaration

module ModuleName where

Note: module names should be in PascalCase.

Obviously replacing the ModuleName with your module name and, similar to Java, the ModuleName should be made up of the path to the module file, ending with the module name. For example let’s assume we’re going to create a Calculator module and our application folder is HaskellBasics, let’s assume we’ve created a Modules folder off of this and within that a Calculator.hs file, hence the ModuleName should look like this

module Modules.Calculator where

We need to add the module to the .cabal build file using the other-modules key, for example

executable HaskellBasics
  main-is:             Main.hs
  other-modules:       Modules.Calculator

Note: We don’t include the file extension for the Calculator module.

If we add more modules then we simply add as comma separated values in the other-modules field in the .cabal file, i.e.

  other-modules: Modules.Calculator, Modules.Output

To import modules into our Main.hs we use the import keyword, like this (we’re importing two modules here).

import Modules.Output
import Modules.Calculator

There’s a lot more we can do in terms of importing modules, for example importing only some functions, like this

import Modules.Calculator (add, sub)

We can also import all function except for some, essentially hiding the module functions, like this

import Modules.Calculator hiding (sub)

The ability to specify the functions available and those not available is useful to help with name clashes etc. Another way to handle such name clashes is to use the module qualified names, for example

main = print (Modules.Calculator.add 10 6)

We can also enforce qualified module names for each function within a module be importing out module like this

import qualified Modules.Calculator

and hence all uses of the functions within this module must be fully qualified.

This can end up requiring a lot more verbosity than we really want, so we can import a qualified module and alias it like this

import qualified Modules.Calculator as C

meaning we can use the function like this

main = print (C.add 10 6)

Note: The alias for the module name must start with a capital letter.

Setting up a Haskel development environment on Windows 10

I wanted to try out Haskell on Windows 10 and figured I’d probably use Visual Code for writing code, here’s the steps to get everything installed and configured.

The simplest way to get everything installed seems to be using chocolatey, see Getting Started.

  1. Install chocolatey
  2. Run Powershell in admin mode and then run choco install haskell-dev
  3. Finally, from Powershell run refreshenv

If all of these steps worked, then just run ghc from the Powershell or a command prompt and you should see some output from ghc.

Let’s now set-up Visual Code (I’ll assume you’ve already got Visual Code installed). There’s a few plugins/extensions for Visual Code for use with Haskell. From Visual Code extensions option…

  • Add Haskell syntax highlighter
  • Also add Haskell-linter
  • To configure the linter, from Visual Code select, File | Preferences | Settings, switch to the code view and add the following
    "haskell.hlint.executablePath": "C:\\ProgramData\\chocolatey\\lib\\ghc\\tools\\ghc-8.10.1\\bin\\ghc.exe"
    

    Chocolatey installs the files into C:\ProgramData\chocolatey\lib, however if you’ve installed ghc by some other means of within another folder then replace the folder with your location.

Finally, let’s write a Haskell “Hello World”. Within Visual Code create the file HelloWorld.hs and add the following code

main = putStrLn "Hello, world!"

Open the Visual Code integrated terminal or open your preferred terminal/shell and from the folder that you saved your HelloWorld.hs file, run

ghc HelloWorld.hs

If all goes to plan you’ll compile the Haskell file to a HelloWorld.exe and you’re done for now.