Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions bower.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
{
"name": "purescript-nonempty",
"version": "1.0.0",
"moduleType": [
"node"
],
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"output"
],
"repository": {
"type": "git",
"url": "git://github.com/paf31/purescript-nonempty.git"
"repository": {
"type": "git",
"url": "git://github.com/paf31/purescript-nonempty.git"
},
"dependencies": {
"purescript-console": "^0.1.0",
Expand Down
14 changes: 13 additions & 1 deletion docs/Data/NonEmpty.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Fold a non-empty structure, collecting results using a binary operation.
foldMap1 :: forall f a s. (Semigroup s, Foldable f) => (a -> s) -> NonEmpty f a -> s
```

Fold a non-empty structure, collecting results in a `Semigroup`.
Fold a non-empty structure, collecting results in a `Semigroup`.

#### `fold1`

Expand All @@ -63,4 +63,16 @@ fold1 :: forall f s. (Semigroup s, Foldable f) => NonEmpty f s -> s

Fold a non-empty structure.

#### `fromNonEmpty`

``` purescript
fromNonEmpty :: forall f a r. (a -> f a -> r) -> NonEmpty f a -> r
```

#### `oneOf`

``` purescript
oneOf :: forall f a. (Alternative f) => NonEmpty f a -> f a
```


27 changes: 19 additions & 8 deletions src/Data/NonEmpty.purs
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
-- | This module defines a generic non-empty data structure, which adds an additional
-- | element to any container type.

module Data.NonEmpty
module Data.NonEmpty
( NonEmpty(..)
, (:|)
, foldl1
, foldMap1
, fold1
, fromNonEmpty
, oneOf
) where

import Prelude

import Data.Foldable
import Data.Traversable
import Control.Alternative (Alternative)
import Control.Alt ((<|>))

import Data.Foldable (Foldable, foldl, foldr, foldMap)
import Data.Traversable (Traversable, traverse, sequence)

-- | A non-empty container of elements of type a.
-- |
Expand All @@ -34,34 +39,40 @@ infix 5 :|
foldl1 :: forall f a s. (Foldable f) => (a -> a -> a) -> NonEmpty f a -> a
foldl1 f (NonEmpty a fa) = foldl f a fa

-- | Fold a non-empty structure, collecting results in a `Semigroup`.
-- | Fold a non-empty structure, collecting results in a `Semigroup`.
foldMap1 :: forall f a s. (Semigroup s, Foldable f) => (a -> s) -> NonEmpty f a -> s
foldMap1 f (NonEmpty a fa) = foldl (\s a1 -> s <> f a1) (f a) fa

-- | Fold a non-empty structure.
fold1 :: forall f s. (Semigroup s, Foldable f) => NonEmpty f s -> s
fold1 = foldMap1 id

fromNonEmpty :: forall f a r. (a -> f a -> r) -> NonEmpty f a -> r
fromNonEmpty f (NonEmpty a fa) = a `f` fa

oneOf :: forall f a. (Alternative f) => NonEmpty f a -> f a
oneOf (NonEmpty a fa) = pure a <|> fa

instance showNonEmpty :: (Show a, Show (f a)) => Show (NonEmpty f a) where
show (NonEmpty a fa) = "(NonEmpty " ++ show a ++ " " ++ show fa ++ ")"

instance eqNonEmpty :: (Eq a, Eq (f a)) => Eq (NonEmpty f a) where
eq (NonEmpty a1 fa1) (NonEmpty a2 fa2) = a1 == a2 && fa1 == fa2

instance ordNonEmpty :: (Ord a, Ord (f a)) => Ord (NonEmpty f a) where
compare (NonEmpty a1 fa1) (NonEmpty a2 fa2) =
compare (NonEmpty a1 fa1) (NonEmpty a2 fa2) =
case compare a1 a2 of
EQ -> compare fa1 fa2
other -> other

instance functorNonEmpty :: (Functor f) => Functor (NonEmpty f) where
map f (NonEmpty a fa) = NonEmpty (f a) (map f fa)

instance foldableNonEmpty :: (Foldable f) => Foldable (NonEmpty f) where
foldMap f (NonEmpty a fa) = f a <> foldMap f fa
foldl f b (NonEmpty a fa) = foldl f (f b a) fa
foldr f b (NonEmpty a fa) = f a (foldr f b fa)

instance traversableNonEmpty :: (Traversable f) => Traversable (NonEmpty f) where
sequence (NonEmpty a fa) = NonEmpty <$> a <*> sequence fa
traverse f (NonEmpty a fa) = NonEmpty <$> f a <*> traverse f fa