{-# START_FILE .gitattributes #-} other/* linguist-documentation index.html linguist-documentation {-# START_FILE .gitignore #-} /.stack-work/ TAGS *.DS_Store {-# START_FILE .hlint.yaml #-} - ignore: {name: Eta reduce} - ignore: {name: Use if} - ignore: {name: Use first} # To generate a suitable file for HLint do: # $ hlint --default > .hlint.yaml {-# START_FILE .travis.yaml #-} # This is the simple Travis configuration, which is intended for use # on applications which do not require cross-platform and # multiple-GHC-version support. For more information and other # options, see: # # https://docs.haskellstack.org/en/stable/travis_ci/ # # Copy these contents into the root directory of your Github project in a file # named .travis.yml # Use new container infrastructure to enable caching sudo: false # Do not choose a language; we provide our own build tools. language: generic # Caching so the next build will be fast too. cache: directories: - $HOME/.stack # Ensure necessary system libraries are present addons: apt: packages: - libgmp-dev before_install: # Download and unpack the stack executable - mkdir -p ~/.local/bin - export PATH=$HOME/.local/bin:$PATH - travis_retry curl -L https://www.stackage.org/stack/linux-x86_64 | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack' install: # Build dependencies - stack --no-terminal --install-ghc test --only-dependencies script: # Build the package, its tests, and its docs and run the tests - stack --no-terminal test --haddock --no-haddock-deps {-# START_FILE .weeder.yaml #-} - package: - name: {{name}} - section: - name: test:test - message: - name: Redundant build-depends entry - depends: base {-# START_FILE LICENSE #-} Copyright {{author-name}}{{^author-name}}Author name here{{/author-name}} (c) {{year}}{{^year}}2017{{/year}} 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 {{author-name}}{{^author-name}}Author name here{{/author-name}} 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. {-# START_FILE Setup.hs #-} import Distribution.Simple main = defaultMain {-# START_FILE package.yaml #-} name: {{name}} version: '0.0.0.1' synopsis: See readme.md description: See readme.md for description. category: project author: {{author-name}}{{^author-name}}Author name here{{/author-name}} maintainer: {{author-email}}{{^author-email}}example@example.com{{/author-email}} copyright: {{copyright}}{{^copyright}}{{year}}{{^year}}2018{{/year}} {{authorName}}{{^authorName}}Author name here{{/authorName}}{{/copyright}} license: BSD3 github: {{github-username}}{{^github-username}}githubuser{{/github-username}}/{{name}} extra-source-files: - readme.md - stack.yaml dependencies: - base >=4.7 && <5 ghc-options: - -Wall - -Wcompat - -Wincomplete-record-updates - -Wincomplete-uni-patterns - -Wredundant-constraints library: source-dirs: src dependencies: - data-default - flow - foldl - formatting - generic-lens-labels - lens - protolude - text ghc-options: - -funbox-strict-fields exposed-modules: - Batterylude executables: {{name}}: main: {{name}}.hs source-dirs: app ghc-options: - -funbox-strict-fields - -threaded - -rtsopts - -with-rtsopts=-N dependencies: - {{name}} - optparse-generic - protolude tests: test: main: test.hs source-dirs: test dependencies: - doctest - protolude {-# START_FILE readme.md #-} {{name}} === [![Build Status](https://travis-ci.org/{{github-username}}{{^github-username}}githubuser{{/github-username}}/{{name}}.svg)](https://travis-ci.org/{{github-username}}{{^github-username}}githubuser{{/github-username}}/{{name}}) [![Hackage](https://img.shields.io/hackage/v/{{name}}.svg)](https://hackage.haskell.org/package/{{name}}) [![lts](https://www.stackage.org/package/{{name}}/badge/lts)](http://stackage.org/lts/package/{{name}}) [![nightly](https://www.stackage.org/package/{{name}}/badge/nightly)](http://stackage.org/nightly/package/{{name}}) recipe --- ``` stack build --test --fast --haddock --exec "$(stack path --local-install-root)/bin/{{name}}" --ghc-options=-Werror --file-watch ``` To generate an index.html ``` stack build --exec "$(stack path --local-bin)/pandoc -f markdown -i other/header.md readme.md other/footer.md -t html -o index.html --filter pandoc-include --mathjax" ``` To generate a per-project hoogle ``` stack hoogle -- generate --local ``` To serve hoogle search ``` stack hoogle -- server --local --port=8080 ``` - [hoogle](http://localhost:8080/) reference --- - [lexi-lambda's opinionated guide](https://lexi-lambda.github.io/blog/2018/02/10/an-opinionated-guide-to-haskell-in-2018/) - [ghc options](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/flags.html#flag-reference) - [pragmas](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/lang.html) - [hoogle](https://www.stackage.org/package/hoogle) - [doctest](https://www.stackage.org/package/doctest) Included [libraries](https://www.stackage.org/) --- - [data-default](https://www.stackage.org/package/data-default) - [foldl](https://www.stackage.org/package/foldl) - [formatting](https://www.stackage.org/package/formatting) - [lens](https://www.stackage.org/package/protolude) - [optparse-generic](https://www.stackage.org/package/optparse-generic) - [protolude](https://www.stackage.org/package/protolude) - [text](https://www.stackage.org/package/text) {-# START_FILE stack.yaml #-} resolver: nightly-2018-02-17 packages: - . extra-deps: # for hoogle - http-conduit-2.3.0 - generic-lens-labels-0.1.0.2 {-# START_FILE app/{{name}}.hs #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE OverloadedLabels #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeOperators #-} {-# OPTIONS_GHC -Wall #-} import Options.Generic import Batterylude newtype Opts w = Opts { numBatteries :: w ::: Maybe Int "number of {{name}} desired" } deriving (Generic) instance ParseRecord (Opts Wrapped) main :: IO () main = do o :: Opts Unwrapped <- unwrapRecord "{{name}}" let n = fromMaybe (view #countBatteries (def::ConfigBatteries)) (numBatteries o) putStrLn ("👍" :: Text) putStrLn (statement1 (def |> #countBatteries .~ n)) statement2 -- | doctests -- >>> :main -- 👍 -- There are 99 batteries. -- This is not a battery. -- This is an effect of a battery. -- {-# START_FILE other/footer.md #-} *** {-# START_FILE other/header.md #-} {-# START_FILE other/lhs.css #-} * { background: transparent; border: 0; font-size: 100%; margin: 0; padding: 0; text-decoration: none; vertical-align: baseline; } body { background-color: #fafafa; color: #3c3c3c; font-family: "Lora", "Seravek", sans-serif; line-height: 1.5; word-wrap: break-word; min-width: 200px; max-width: 900px; margin: 0 auto; padding: 3em; } body a { background-color: transparent; color: #3c3c3c; border-bottom-style: solid; border-bottom-width: 1px; border-bottom-color: #969696; text-decoration: none; } body a:visited { border-bottom-style: solid; border-bottom-width: 1px; border-bottom-color: #bd67c9; text-decoration: none; } body a:visited:hover { opacity: 0.7; } body a:hover { opacity: 0.7; } body h1 { font-size: 2em; padding-top: 1em; padding-bottom: 0.5em; } body h2 { font-size: 1.5em; padding-top: 1em; padding-bottom: 0.5em; } body h1, body h2 { font-family: "Raleway", serif; color: #222222; } body h1 a, body h2 a { background-color: transparent; color: #222222; text-decoration: none; border-bottom-style: solid; border-bottom-width: 2px; border-bottom-color: #969696; } body h1 a:visited, body h2 a:visited { opacity: 0.7; color: #222222; text-decoration: none; border-bottom-style: solid; border-bottom-width: 2px; border-bottom-color: #bd67c9; } body h1 a:hover, body h2 a:hover { opacity: 0.7; text-decoration: none; } body blockquote { border-left: 0.25rem solid #c8c8c8; font-style: italic; margin: 0.5rem 0 1rem 0; padding: 0 0 0 1rem; color: #646464; } body .footer { color: #888888; font-size: 0.75em; text-align: right; } body hr { height: 0; margin: 1em 0; overflow: hidden; background: transparent; border: 0; border-bottom: 1px solid #c8c8c8; } body pre { color: #ab1f27; background-color: #f5f0f0; padding: 0.75em; overflow: auto; } body ul { margin: 0.5rem 0; padding-left: 0; } body ul li { counter-increment: this; line-height: 1.313em; list-style: none; position: relative; } body ul li:after { color: #646464; content: "-"; left: -1em; position: absolute; top: 0; } .sourceCode { background-color: whitesmoke; color: #284628; font-family: "Inconsolata", mono; font-size: 1em; } .sourceCode .ot, .sourceCode .kw { color: #284628; } .sourceCode .dt { color: #ab1f27; } .sourceCode .dv, .sourceCode .st { color: #2536d6; } .sourceCode .co { color: #646464; font-style: italic; } .sourceCode .fu { color: #e347e4; } {-# START_FILE src/Batterylude.hs #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE OverloadedLabels #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeOperators #-} {-# OPTIONS_GHC -Wall #-} {-# OPTIONS_GHC -Wno-unused-top-binds #-} module Batterylude ( module Protolude , (<>) , (.) , id , String , module Control.Lens , module Flow , module Data.Default , module Formatting , statement1 , statement2 , ConfigBatteries(ConfigBatteries) ) where import Control.Category ((.), id) import qualified Control.Foldl as L import Control.Lens hiding (Fold, Strict, Unwrapped, Wrapped, (.>), (<&>), (<.), (<.>), (<|), (|>), from, to, uncons, unsnoc) import Data.Default import Data.Generics.Labels () import Data.Semigroup ((<>)) import qualified Data.Text as Text import qualified Data.Text.IO as Text import Flow import Formatting import GHC.Base (String) import Protolude hiding ((%), (.), (<>)) -- | there is invariably a Config for a project data ConfigBatteries = ConfigBatteries { countBatteries :: Int , hasBatteries :: Bool } deriving (Show, Eq, Generic) instance Default ConfigBatteries where def = ConfigBatteries 99 True -- | formatting example statement1 :: ConfigBatteries -> Text statement1 cfg = sformat ("There " %text % " " %text % " " %text%".") (bool "are" "is" (view #countBatteries cfg == 1)) (bool "no" (show <| view #countBatteries cfg) (view #hasBatteries cfg)) (bool "batteries" "battery" (view #countBatteries cfg == 1)) -- | foldl example statement2 :: IO () statement2 = do Text.putStrLn <| L.fold (L.Fold (\x a -> x <> " " <> a) ("This" :: Text) id) ["is", "not", "a", "battery."] Text.putStrLn <| Text.intercalate " " ["This", "is", "an", "effect", "of", "a", "battery."] {-# START_FILE test/test.hs #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeOperators #-} {-# OPTIONS_GHC -Wall #-} module Main where import Protolude import Test.DocTest main :: IO () main = doctest ["app/{{name}}.hs"]