praxis

Various programming exercises.
Log | Files | Refs

commit 684f90ec80cd696e2ec0277b3136d85a96b282ef
parent 8064dc247437f3ecd9b8cda573fa189d1c47e859
Author: Jared Tobin <jared@jtobin.ca>
Date:   Sat, 28 Feb 2015 23:48:37 +1300

Add currency converter example.

Diffstat:
A.gitignore | 3+++
A20150227_currency/LICENSE | 20++++++++++++++++++++
A20150227_currency/Setup.hs | 2++
A20150227_currency/cabal.sandbox.config | 25+++++++++++++++++++++++++
A20150227_currency/src-exec/Main.hs | 32++++++++++++++++++++++++++++++++
A20150227_currency/src-lib/Currency.hs | 35+++++++++++++++++++++++++++++++++++
A20150227_currency/x20150227-currency.cabal | 35+++++++++++++++++++++++++++++++++++
7 files changed, 152 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,3 @@ +dist +.sandbox +.cabal-sandbox diff --git a/20150227_currency/LICENSE b/20150227_currency/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2015 Jared Tobin + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/20150227_currency/Setup.hs b/20150227_currency/Setup.hs @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain diff --git a/20150227_currency/cabal.sandbox.config b/20150227_currency/cabal.sandbox.config @@ -0,0 +1,25 @@ +-- This is a Cabal package environment file. +-- THIS FILE IS AUTO-GENERATED. DO NOT EDIT DIRECTLY. +-- Please create a 'cabal.config' file in the same directory +-- if you want to change the default settings for this sandbox. + + +local-repo: /Users/jtobin/projects/praxis/20150227_currency/.cabal-sandbox/packages +logs-dir: /Users/jtobin/projects/praxis/20150227_currency/.cabal-sandbox/logs +world-file: /Users/jtobin/projects/praxis/20150227_currency/.cabal-sandbox/world +user-install: False +package-db: /Users/jtobin/projects/praxis/20150227_currency/.cabal-sandbox/x86_64-osx-ghc-7.8.3-packages.conf.d +build-summary: /Users/jtobin/projects/praxis/20150227_currency/.cabal-sandbox/logs/build.log + +install-dirs + prefix: /Users/jtobin/projects/praxis/20150227_currency/.cabal-sandbox + bindir: $prefix/bin + libdir: $prefix/lib + libsubdir: $abi/$pkgkey + libexecdir: $prefix/libexec + datadir: $prefix/share + datasubdir: $abi/$pkgid + docdir: $datadir/doc/$abi/$pkgid + htmldir: $docdir/html + haddockdir: $htmldir + sysconfdir: $prefix/etc diff --git a/20150227_currency/src-exec/Main.hs b/20150227_currency/src-exec/Main.hs @@ -0,0 +1,32 @@ + +module Main where + +import Currency +import Data.Scientific +import Options.Applicative +import Options.Applicative.Types + +main :: IO () +main = execParser parserOptions >>= runProgram + +data ExchangeOptions = ExchangeOptions Scientific String String + +-- | Options parser options. +parserOptions :: ParserInfo ExchangeOptions +parserOptions = info (helper <*> opts) fullDesc where + opts = + ExchangeOptions + <$> argument parseSci (metavar "AMOUNT") + <*> argument str (metavar "CURRENCY") + <*> argument str (metavar "CURRENCY") + +runProgram :: ExchangeOptions -> IO () +runProgram (ExchangeOptions d x y) = do + val <- query d x y + putStrLn $ show d <> "@" <> x <> "/" <> y <> ": " <> show val + +parseSci :: ReadM Scientific +parseSci = do + sci <- readerAsk + return $ read sci + diff --git a/20150227_currency/src-lib/Currency.hs b/20150227_currency/src-lib/Currency.hs @@ -0,0 +1,35 @@ +{-# OPTIONS_GHC -Wall #-} +{-# LANGUAGE OverloadedStrings #-} + +module Currency (query) where + +import Control.Lens +import Data.Aeson +import Data.Aeson.Lens +import Data.Monoid +import Data.Scientific (Scientific) +import Data.Text (Text) +import qualified Data.Text as Text +import Network.Wreq + +apiUrl :: String +apiUrl = "http://www.freecurrencyconverterapi.com/api/v3/convert" + +convertQuery :: String -> String -> String +convertQuery x y = apiUrl <> "?q=" <> x <> "_" <> y <> "&compact=y" + +tp :: String -> Text +tp = Text.pack + +query :: Scientific -> String -> String -> IO Scientific +query d x y = do + r <- asJSON =<< get (convertQuery x y) :: IO (Response Value) + let replyBody = do + reply <- r ^? responseBody . key (tp x <> "_" <> tp y) . _Object + val <- reply ^. at "val" + val ^? _Number + + case replyBody of + Nothing -> error "invalid currency pair" + Just v -> return $ d * v + diff --git a/20150227_currency/x20150227-currency.cabal b/20150227_currency/x20150227-currency.cabal @@ -0,0 +1,35 @@ +name: x20150227-currency +version: 0.1.0.0 +license: MIT +license-file: LICENSE +author: Jared Tobin +maintainer: jared@jtobin.ca +build-type: Simple +cabal-version: >=1.10 + +library + exposed-modules: Currency + hs-source-dirs: src-lib + default-language: Haskell2010 + build-depends: + aeson >= 0.8.0.2 + , base >= 4.7 && < 4.8 + , containers >= 0.5.5.1 + , lens >= 3.7 + , lens-aeson >= 1.0.0.3 + , scientific >= 0.3.3.7 + , text >= 1.2.0.4 + , wreq >= 0.3.0.1 + +executable exchange-rate + main-is: Main.hs + hs-source-dirs: src-exec + default-language: Haskell2010 + ghc-options: + -Wall -Werror -O2 + build-depends: + base >= 4.7.0.1 && < 4.8 + , optparse-applicative >= 0.11.0.1 + , scientific >= 0.3.3.7 + , x20150227-currency >= 0.1.0.0 +