четверг, 20 апреля 2017 г.

Parse date in free format from JSON with Aeson

Already is night, so post will be short :) This is an example how to parse JSON data (date stamp) in free format:

{-# LANGUAGE OverloadedStrings #-}
module Main where

import           Control.Monad        (mzero)
import           Data.Aeson
import qualified Data.ByteString.Lazy as B
import           Data.Text
import           Data.Time
import           Data.Maybe (fromJust)

main :: IO ()
main = getJSON >>= print

data Person =
  Person {  name  :: !Text
          , age   :: Int
          , birth :: UTCTime
            } deriving Show

prsTime :: String -> UTCTime
prsTime = fromJust . parseTimeM True defaultTimeLocale "%0Y,%m"

instance FromJSON Person where
  parseJSON (Object v) =
      Person <$> v .: "name"
             <*> v .: "age"
             <*> (prsTime <$> v .: "birth")
  parseJSON _ = mzero


jsonFile :: FilePath
jsonFile = "js.json"

getJSON :: IO (Maybe Person)
getJSON = decode <$> B.readFile jsonFile

To build I change .cabal file to:

...
build-depends:       base
                     , js
                     , text
                     , aeson
                     , bytestring >= 0.10
                     , time
...

Our testing JSON file D:\prj\js\js.json will be:

{
    "name": "alex",
    "age": 20,
    "birth": "2017,10"
}

so, as you can see our date has format "YYYY,mm". Build and run as usual:

D:\prj\js> stack build
D:\prj\js> stack exec js-exe
Just (Person {name = "alex", age = 20, birth = 2017-10-01 00:00:00 UTC})

пятница, 14 апреля 2017 г.

Linking HDBC/Sqlite3 on Haskell stack under Windows

To link your Haskell application with HDBC for Sqlite3 under Windows, you have to:

install sqlite3 dev C package (headers and libs)

  • go to your Haskell MSYS2 installation (for example, D:\apps\haskell\8.0.2\msys\) and run msys2.exe
  • in opened terminal run
pacman -Syu
# if needed - close terminal and run again
pacman -Su
pacman -S libsqlite-devel
pacman -S sqlite # to have CLI tool

modify cabal and stack.yaml files

  • add to stack.yaml:
...
extra-deps: [HDBC-sqlite3-2.3.3.1]
...
extra-include-dirs: ["d:/apps/haskell/8.0.2/msys/usr/include"]
extra-lib-dirs: ["d:/apps/haskell/8.0.2/msys/usr/lib"]
...
  • add to cabal file:
  build-depends:       base >= 4.7 && < 5
                     , HDBC
                     , HDBC-sqlite3
  • now you can import modules:
import Database.HDBC
import Database.HDBC.Sqlite3
...

Man page ASCII output tags

Simple way to output man page in ASCII only format (no any special symbols):

groff -P\-c -mandoc -Tascii file.1|col -bx > file.txt

file.txt is formatted as you see man output on your screen.

суббота, 1 апреля 2017 г.

Haskell Mustache templating usage

This is a small example how to use Mustache template implementation in Haskell. Main idea of Mustache is to avoid complex syntax and all semantics is getting from variable itself: boolean vairables using as sections allow to hide/show its content, lists - to enumerate its content, etc. Example is very simple! You need to add mustache and text packages into your .cabal file only.

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes       #-}
module Main where
import qualified Data.Text             as T
import           Text.Mustache
import           Text.Mustache.Compile

-- Tutorial: https://www.stackbuilders.com/tutorials/haskell/mustache-templates/

templ :: Template
templ = [mustache|We are the good Company "{{name}}":
{{#persons}}
- my name is {{name}} and I'm {{age}} years old
{{/persons}}
|]

data Company = Company {
  cName :: T.Text
, cPersons :: [Person]
                       }
instance ToMustache Company where
  toMustache c = object
    [ "persons" ~> cPersons c
    , "name" ~> cName c
    ]


data Person = Person {
  pName :: T.Text
, pAge  :: Int
                     }
instance ToMustache Person where
  toMustache per = object
    [ "age" ~> pAge per
    , "name" ~> pName per
    ]

main :: IO ()
main = do
  let c = Company "MS" [Person "Alex" 20, Person "Jane" 21, Person "John" 25]
  putStr $ T.unpack $ substitute templ $ c

Output is:

We are the good Company "MS":
- my name is Alex and I'm 20 years old
- my name is Jane and I'm 21 years old
- my name is John and I'm 25 years old

Haskell/stack on Windows in non-standard location

Often today we need to install Haskell on Windows in not-default location - due to SSD disks, for example, in D:\somewhere instead of standard C:\. This tutorial shows how to do it.

Install stack

First, we need to install stack in non-typical location. Create directory D:\stackroot - all stack caches will be located there. Then add to environment variable binding STACK_ROOT=D:\stackroot. Install stack also on the same disk, for example, D:\apps\stack (or put in there if use download binary).

Now install the compiler as usual. After installation you will call stack with --system-ghc. Another (and right!) solution is to add next setting in D:\stackroot\config.yaml:

local-bin-path: D:\apps\haskell\8.0.2\bin
system-ghc: true

I suppose you installed compiler in D:\apps\haskell (and it has version 8.0.2). If not, change value to your path.

Also you should add to environment variable PATH next path: d:\apps\haskell\8.0.2\msys\usr\bin.

Now you can use stack to install other packages even which needs ./configure script run.

To check what paths uses stack, run stack path.

Integration with Spacemacs

Install with stack packages:

  • apply-refact
  • hlint
  • stylish-haskell
  • hasktags
  • hoogle (for local queries)
  • ghc-mod
  • intero (optional, because intero-layer install it byself)
  • hindent

In Spacemacs you should to add Haskell layer. To see types hints you must run Haskell REPL (SPC m h s b IMHO:). Also you must add syntax-checking layer, auto-completion. And sure, path to stack must be in PATH environment variable :)