diff --git a/Gruntfile.js b/Gruntfile.js deleted file mode 100644 index d58eb63..0000000 --- a/Gruntfile.js +++ /dev/null @@ -1,42 +0,0 @@ -module.exports = function(grunt) { - - "use strict"; - - grunt.initConfig({ - - libFiles: [ - "src/**/*.purs", - "bower_components/purescript-*/src/**/*.purs", - ], - - clean: ["output"], - - pscMake: ["<%=libFiles%>"], - dotPsci: ["<%=libFiles%>"], - pscDocs: { - readme: { - src: "src/**/*.purs", - dest: "README.md" - } - }, - jsvalidate: { - options:{ - globals: {}, - esprimaOptions: {}, - verbose: false - }, - targetName:{ - files:{ - src: ['output/Data.Enum/*.js'] - } - } - } - }); - - grunt.loadNpmTasks('grunt-jsvalidate'); - grunt.loadNpmTasks("grunt-contrib-clean"); - grunt.loadNpmTasks("grunt-purescript"); - - grunt.registerTask("make", ["pscMake", "dotPsci", "pscDocs", "jsvalidate"]); - grunt.registerTask("default", ["make"]); -}; diff --git a/README.md b/README.md index 5ff9ea8..7c091fd 100644 --- a/README.md +++ b/README.md @@ -1,154 +1,15 @@ -# Module Documentation +# purescript-enums -## Module Data.Enum +[![Build Status](https://travis-ci.org/purescript/purescript-enums.svg?branch=master)](https://travis-ci.org/purescript/purescript-enums) -#### `Cardinality` +Operations for small ordered sum types. -``` purescript -newtype Cardinality a - = Cardinality Int -``` - - -#### `runCardinality` - -``` purescript -runCardinality :: forall a. Cardinality a -> Int -``` - - -#### `Enum` - -``` purescript -class (Bounded a) <= Enum a where - cardinality :: Cardinality a - succ :: a -> Maybe a - pred :: a -> Maybe a - toEnum :: Int -> Maybe a - fromEnum :: a -> Int -``` - -Type class for enumerations. This should not be considered a part of a -numeric hierarchy, ala Haskell. Rather, this is a type class for small, -ordered sum types with statically-determined cardinality and the ability -to easily compute successor and predecessor elements. e.g. `DayOfWeek`, etc. - -Laws: - -- ```succ bottom >>= succ >>= succ ... succ [cardinality - 1 times] == top``` -- ```pred top >>= pred >>= pred ... pred [cardinality - 1 times] == bottom``` -- ```e1 `compare` e2 == fromEnum e1 `compare` fromEnum e2``` -- ```forall a > bottom: pred a >>= succ == Just a``` -- ```forall a < top: succ a >>= pred == Just a``` -- ```pred >=> succ >=> pred = pred``` -- ```succ >=> pred >=> succ = succ``` -- ```toEnum (fromEnum a) = Just a``` -- ```forall a > bottom: fromEnum <$> pred a = Just (fromEnum a - 1)``` -- ```forall a < top: fromEnum <$> succ a = Just (fromEnum a + 1)``` +## Installation -#### `defaultSucc` - -``` purescript -defaultSucc :: forall a. (Int -> Maybe a) -> (a -> Int) -> a -> Maybe a ``` - -```defaultSucc toEnum fromEnum = succ``` - -#### `defaultPred` - -``` purescript -defaultPred :: forall a. (Int -> Maybe a) -> (a -> Int) -> a -> Maybe a +bower install purescript-enums ``` -```defaultPred toEnum fromEnum = pred``` - -#### `defaultToEnum` - -``` purescript -defaultToEnum :: forall a. (a -> Maybe a) -> a -> Int -> Maybe a -``` - -Runs in `O(n)` where `n` is `fromEnum a` - -```defaultToEnum succ bottom = toEnum``` - -#### `defaultFromEnum` - -``` purescript -defaultFromEnum :: forall a. (a -> Maybe a) -> a -> Int -``` - -Runs in `O(n)` where `n` is `fromEnum a` - -```defaultFromEnum pred = fromEnum``` - -#### `enumFromTo` - -``` purescript -enumFromTo :: forall a. (Enum a) => a -> a -> [a] -``` - -Property: ```fromEnum a = a', fromEnum b = b' => forall e', a' <= e' <= b': Exists e: toEnum e' = Just e``` - -Following from the propery of `intFromTo`, we are sure all elements in `intFromTo (fromEnum a) (fromEnum b)` are `Just`s. - -#### `enumFromThenTo` - -``` purescript -enumFromThenTo :: forall a. (Enum a) => a -> a -> a -> [a] -``` - -`[a,b..c]` - -Correctness for using `fromJust` is the same as for `enumFromTo`. - -#### `intFromTo` - -``` purescript -intFromTo :: Int -> Int -> [Int] -``` - -Property: ```forall e in intFromTo a b: a <= e <= b``` - -#### `intStepFromTo` - -``` purescript -intStepFromTo :: Int -> Int -> Int -> [Int] -``` - -Property: ```forall e in intStepFromTo step a b: a <= e <= b``` - -#### `enumChar` - -``` purescript -instance enumChar :: Enum Char -``` - -## Instances - -#### `enumMaybe` - -``` purescript -instance enumMaybe :: (Enum a) => Enum (Maybe a) -``` - - -#### `enumBoolean` - -``` purescript -instance enumBoolean :: Enum Boolean -``` - - -#### `enumTuple` - -``` purescript -instance enumTuple :: (Enum a, Enum b) => Enum (Tuple a b) -``` - - -#### `enumEither` +## Module documentation -``` purescript -instance enumEither :: (Enum a, Enum b) => Enum (Either a b) -``` \ No newline at end of file +- [Data.Enum](docs/Data.Enum.md) diff --git a/bower.json b/bower.json index 69092be..93c3908 100644 --- a/bower.json +++ b/bower.json @@ -6,23 +6,23 @@ "purescript" ], "license": "MIT", + "repository": { + "type": "git", + "url": "git://github.com/purescript/purescript-enums.git" + }, "ignore": [ "**/.*", "bower_components", "node_modules", "output", - "tests", - "tmp", + "test", "bower.json", - "Gruntfile.js", + "gulpfile.js", "package.json" ], "dependencies": { - "purescript-integers": "~0.2.0", - "purescript-maybe": "~0.3.0", - "purescript-tuples": "~0.4.0", - "purescript-either": "~0.2.0", - "purescript-strings": "~0.5.0", - "purescript-unfoldable": "~0.4.0" + "purescript-either": "^0.2.0", + "purescript-strings": "^0.5.0", + "purescript-unfoldable": "^0.4.0" } } diff --git a/docs/Data.Enum.md b/docs/Data.Enum.md new file mode 100644 index 0000000..32b7be2 --- /dev/null +++ b/docs/Data.Enum.md @@ -0,0 +1,126 @@ +## Module Data.Enum + +#### `Cardinality` + +``` purescript +newtype Cardinality a + = Cardinality Int +``` + +#### `runCardinality` + +``` purescript +runCardinality :: forall a. Cardinality a -> Int +``` + +#### `Enum` + +``` purescript +class (Bounded a) <= Enum a where + cardinality :: Cardinality a + succ :: a -> Maybe a + pred :: a -> Maybe a + toEnum :: Int -> Maybe a + fromEnum :: a -> Int +``` + +Type class for enumerations. This should not be considered a part of a +numeric hierarchy, ala Haskell. Rather, this is a type class for small, +ordered sum types with statically-determined cardinality and the ability +to easily compute successor and predecessor elements. e.g. `DayOfWeek`, etc. + +Laws: + +- ```succ bottom >>= succ >>= succ ... succ [cardinality - 1 times] == top``` +- ```pred top >>= pred >>= pred ... pred [cardinality - 1 times] == bottom``` +- ```e1 `compare` e2 == fromEnum e1 `compare` fromEnum e2``` +- ```forall a > bottom: pred a >>= succ == Just a``` +- ```forall a < top: succ a >>= pred == Just a``` +- ```pred >=> succ >=> pred = pred``` +- ```succ >=> pred >=> succ = succ``` +- ```toEnum (fromEnum a) = Just a``` +- ```forall a > bottom: fromEnum <$> pred a = Just (fromEnum a - 1)``` +- ```forall a < top: fromEnum <$> succ a = Just (fromEnum a + 1)``` + +##### Instances +``` purescript +instance enumChar :: Enum Char +instance enumMaybe :: (Enum a) => Enum (Maybe a) +instance enumBoolean :: Enum Boolean +instance enumTuple :: (Enum a, Enum b) => Enum (Tuple a b) +instance enumEither :: (Enum a, Enum b) => Enum (Either a b) +``` + +#### `defaultSucc` + +``` purescript +defaultSucc :: forall a. (Int -> Maybe a) -> (a -> Int) -> a -> Maybe a +``` + +```defaultSucc toEnum fromEnum = succ``` + +#### `defaultPred` + +``` purescript +defaultPred :: forall a. (Int -> Maybe a) -> (a -> Int) -> a -> Maybe a +``` + +```defaultPred toEnum fromEnum = pred``` + +#### `defaultToEnum` + +``` purescript +defaultToEnum :: forall a. (a -> Maybe a) -> a -> Int -> Maybe a +``` + +Runs in `O(n)` where `n` is `fromEnum a` + +```defaultToEnum succ bottom = toEnum``` + +#### `defaultFromEnum` + +``` purescript +defaultFromEnum :: forall a. (a -> Maybe a) -> a -> Int +``` + +Runs in `O(n)` where `n` is `fromEnum a` + +```defaultFromEnum pred = fromEnum``` + +#### `enumFromTo` + +``` purescript +enumFromTo :: forall a. (Enum a) => a -> a -> Array a +``` + +Property: ```fromEnum a = a', fromEnum b = b' => forall e', a' <= e' <= b': Exists e: toEnum e' = Just e``` + +Following from the propery of `intFromTo`, we are sure all elements in `intFromTo (fromEnum a) (fromEnum b)` are `Just`s. + +#### `enumFromThenTo` + +``` purescript +enumFromThenTo :: forall a. (Enum a) => a -> a -> a -> Array a +``` + +`[a,b..c]` + +Correctness for using `fromJust` is the same as for `enumFromTo`. + +#### `intFromTo` + +``` purescript +intFromTo :: Int -> Int -> Array Int +``` + +Property: ```forall e in intFromTo a b: a <= e <= b``` + +#### `intStepFromTo` + +``` purescript +intStepFromTo :: Int -> Int -> Int -> Array Int +``` + +Property: ```forall e in intStepFromTo step a b: a <= e <= b``` + + diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..17225af --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,51 @@ +/* jshint node: true */ +"use strict"; + +var gulp = require("gulp"); +var plumber = require("gulp-plumber"); +var purescript = require("gulp-purescript"); +var rimraf = require("rimraf"); + +var sources = [ + "src/**/*.purs", + "bower_components/purescript-*/src/**/*.purs" +]; + +var foreigns = [ + "src/**/*.js", + "bower_components/purescript-*/src/**/*.js" +]; + +gulp.task("clean-docs", function (cb) { + rimraf("docs", cb); +}); + +gulp.task("clean-output", function (cb) { + rimraf("output", cb); +}); + +gulp.task("clean", ["clean-docs", "clean-output"]); + +gulp.task("make", function() { + return gulp.src(sources) + .pipe(plumber()) + .pipe(purescript.pscMake({ ffi: foreigns })); +}); + +gulp.task("docs", ["clean-docs"], function () { + return gulp.src(sources) + .pipe(plumber()) + .pipe(purescript.pscDocs({ + docgen: { + "Data.Enum": "docs/Data.Enum.md" + } + })); +}); + +gulp.task("dotpsci", function () { + return gulp.src(sources) + .pipe(plumber()) + .pipe(purescript.dotPsci()); +}); + +gulp.task("default", ["make", "docs", "dotpsci"]); diff --git a/package.json b/package.json index 11c3a6d..0c0f2c6 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { "private": true, - "dependencies": { - "grunt": "~0.4.4", - "grunt-purescript": "~0.6.0", - "grunt-contrib-clean": "~0.6.0", - "grunt-jsvalidate": "~0.2.2" + "devDependencies": { + "gulp": "^3.8.11", + "gulp-plumber": "^1.0.0", + "gulp-purescript": "^0.5.0-rc.1", + "rimraf": "^2.3.3" } } diff --git a/src/Data/Enum.purs b/src/Data/Enum.purs index 9b21b88..f128efd 100644 --- a/src/Data/Enum.purs +++ b/src/Data/Enum.purs @@ -18,14 +18,12 @@ module Data.Enum ) where import Prelude - -import Data.Maybe +import Data.Char (fromCharCode, toCharCode) import Data.Either -import Data.Tuple -import Data.Char +import Data.Maybe import Data.Maybe.Unsafe +import Data.Tuple import Data.Unfoldable -import Data.Int (fromNumber) newtype Cardinality a = Cardinality Int