cluss-0.2: simple alternative to type classes

Copyright(c) Yusuke Matsushita 2014
LicenseBSD3
MaintainerYusuke Matsushita
Stabilityprovisional
Portabilityportable
Safe HaskellTrustworthy
LanguageHaskell2010

Type.Cluss

Contents

Description

Basic tools for clusses. Examples show how to use them.

Template haskell tools are in the module Type.Cluss.TH.

Synopsis

Clusses

class In as a where Source

In as is a cluss, where as is a list of type patterns. Normally, as is concrete and does not contain any type variables, like In [Binary (->) (Show >|< This), Type String] a.

When a satisfies In as a, you can use the method proj :: AllOf as f -> f a.

Internally, "type pattern matching" is executed by Where, a closed type family, which cannot check if a type satisfies a constraint. If as has many type patterns that can match a, only the first one matches a.

Clusses call for some language extensions. Basically, this language pragma will do.

{-# LANGUAGE DataKinds, FlexibleContexts, TypeOperators #-}

Methods

proj :: AllOf as t -> t a Source

Instances

In' k (Where k as as a) as as a => In k as a 

type family Has as a :: Bool Source

Has as a judges whether a type a belongs to a cluss In as, on some level. When not sure, Has always returns True. For example, when as has Unary [] Show and a is [b], Has can't judge if b belongs to Show since the instances of Show is open, but it assumes that b belongs to Show and returns True.

Instances

type Has k as a 

Type Patterns

Type patterns are used in the type list (first parameter) of In. Each type pattern corresponds to the head of an instance declaration for a type class, namely, instance ... where.

data Type a Source

The empty type Type a is a type pattern, where a is a type. The type pattern Type Int corresponds to instance C Int where ... (where C is a corresponding type class), for example. Note that the type variable a can be of any kind: a could be of the kind * -> *, for example.

Instances

data AllOf' k ts ((:) * (Type k a) as) = And (t a) (AllOf' k ts as t) 

data AnyType p Source

The empty type AnyType p is a type pattern, where p is a type function from a type to a constraint. The type pattern AnyType Show basically corresponds to instance Show a => C a where ... (where C is a corresponding type class), for example, but AnyType is much more useful in that it does not cause overlapping instances whereas C is likely to, because cluss instances are prioritized.

Instances

data AllOf' k ts ((:) * (AnyType k p) as) = AndAny (forall a. p a => t a) (AllOf' k ts as t) 

data a <| p infixl 7 Source

The empty type a <| p is a type pattern, where a is a type constructor, and p is a type function to a constraint from the type variables for the constructor a. The type pattern [] <| Show corresponds to instance Show a => C [a] where ... (where C is a corresponding type class), for example.

You can replace Unary, Binary, ..., and Denary with <|, but you can sometimes save the effort of annotating kinds using Unary, Binary, ..., or Denary instead of <|, especially when using the PolyKinds extension, because the kinds of the parameters in Unary, Binary, ..., and Denary are restricted as described below.

Instances

data AllOf' k ts ((:) * (Denary k1 k2 k3 k4 k5 k6 k7 k8 k9 k10 k a p) as) = And10 (forall b c d e f g h i j k. Modify10 k k k k k k k k k k k (a b c d e f g h i j k) (In k ts) p b c d e f g h i j k => t (a b c d e f g h i j k)) (AllOf' k ts as t) 
data AllOf' k ts ((:) * (Nonary k1 k2 k3 k4 k5 k6 k7 k8 k9 k a p) as) = And9 (forall b c d e f g h i j. Modify9 k k k k k k k k k k (a b c d e f g h i j) (In k ts) p b c d e f g h i j => t (a b c d e f g h i j)) (AllOf' k ts as t) 
data AllOf' k ts ((:) * (Octary k1 k2 k3 k4 k5 k6 k7 k8 k a p) as) = And8 (forall b c d e f g h i. Modify8 k k k k k k k k k (a b c d e f g h i) (In k ts) p b c d e f g h i => t (a b c d e f g h i)) (AllOf' k ts as t) 
data AllOf' k ts ((:) * (Septenary k1 k2 k3 k4 k5 k6 k7 k a p) as) = And7 (forall b c d e f g h. Modify7 k k k k k k k k (a b c d e f g h) (In k ts) p b c d e f g h => t (a b c d e f g h)) (AllOf' k ts as t) 
data AllOf' k ts ((:) * (Senary k1 k2 k3 k4 k5 k6 k a p) as) = And6 (forall b c d e f g. Modify6 k k k k k k k (a b c d e f g) (In k ts) p b c d e f g => t (a b c d e f g)) (AllOf' k ts as t) 
data AllOf' k ts ((:) * (Quinary k1 k2 k3 k4 k5 k a p) as) = And5 (forall b c d e f. Modify5 k k k k k k (a b c d e f) (In k ts) p b c d e f => t (a b c d e f)) (AllOf' k ts as t) 
data AllOf' k ts ((:) * (Quaternary k1 k2 k3 k4 k a p) as) = And4 (forall b c d e. Modify4 k k k k k (a b c d e) (In k ts) p b c d e => t (a b c d e)) (AllOf' k ts as t) 
data AllOf' k ts ((:) * (Ternary k1 k2 k3 k a p) as) = And3 (forall b c d. Modify3 k k k k (a b c d) (In k ts) p b c d => t (a b c d)) (AllOf' k ts as t) 
data AllOf' k ts ((:) * (Binary k1 k2 k a p) as) = And2 (forall b c. Modify2 k k k (a b c) (In k ts) p b c => t (a b c)) (AllOf' k ts as t) 
data AllOf' k ts ((:) * (Unary k1 k a p) as) = And1 (forall b. Modify k k (a b) (In k ts) p b => t (a b)) (AllOf' k ts as t) 

type Unary a p = a <| p Source

a <| p, with a being of the kind i -> k, and p of the kind i -> Constraint.

type Binary a p = a <| p Source

a <| p, with a being of the kind i -> i2 -> k, and p of the kind i -> i2 -> Constraint.

type Ternary a p = a <| p Source

a <| p, with a being of the kind i -> i2 -> i3 -> k, and p of the kind i -> i2 -> i3 -> Constraint.

type Quaternary a p = a <| p Source

a <| p, with a being of the kind i -> i2 -> i3 -> i4 -> k, and p of the kind i -> i2 -> i3 -> i4 -> Constraint.

type Quinary a p = a <| p Source

a <| p, with a being of the kind i -> i2 -> i3 -> i4 -> i5 -> k, and p of the kind i -> i2 -> i3 -> i4 -> i5 -> Constraint.

type Senary a p = a <| p Source

a <| p, with a being of the kind i -> i2 -> i3 -> i4 -> i5 -> i6 -> k, and p of the kind i -> i2 -> i3 -> i4 -> i5 -> i6 -> Constraint.

type Septenary a p = a <| p Source

a <| p, with a being of the kind i -> i2 -> i3 -> i4 -> i5 -> i6 -> i7 -> k, and p of the kind i -> i2 -> i3 -> i4 -> i5 -> i6 -> i7 -> Constraint.

type Octary a p = a <| p Source

a <| p, with a being of the kind i -> i2 -> i3 -> i4 -> i5 -> i6 -> i7 -> i8 -> k, and p of the kind i -> i2 -> i3 -> i4 -> i5 -> i6 -> i7 -> i8 -> Constraint.

type Nonary a p = a <| p Source

a <| p, with a being of the kind i -> i2 -> i3 -> i4 -> i5 -> i6 -> i7 -> i8 -> i9 -> k, and p of the kind i -> i2 -> i3 -> i4 -> i5 -> i6 -> i7 -> i8 -> i9 -> Constraint.

type Denary a p = a <| p Source

a <| p, with a being of the kind i -> i2 -> i3 -> i4 -> i5 -> i6 -> i7 -> i8 -> i9 -> i10 -> k, and p of the kind i -> i2 -> i3 -> i4 -> i5 -> i6 -> i7 -> i8 -> i9 -> i10 -> Constraint.

Instance Products

type AllOf as = AllOf' as as Source

AllOf as f is a tuple that contains values of the type f a, where a can be any type that satisfies In as a. Each value corresponds to each type pattern, and the values in AllOf as f must be in the same order as the type patterns in as. And, And1, And2, ..., and And10 are used to combine the values, where None must be added at the end. You have to use And for Type a, And1 for Unary a p, And2 for Binary a p, ..., and And10 for Denary a p.

data family AllOf' ts as t Source

Instances

data AllOf' k ts ([] *) = None 
data AllOf' k ts ((:) * (Denary k1 k2 k3 k4 k5 k6 k7 k8 k9 k10 k a p) as) = And10 (forall b c d e f g h i j k. Modify10 k k k k k k k k k k k (a b c d e f g h i j k) (In k ts) p b c d e f g h i j k => t (a b c d e f g h i j k)) (AllOf' k ts as t) 
data AllOf' k ts ((:) * (Nonary k1 k2 k3 k4 k5 k6 k7 k8 k9 k a p) as) = And9 (forall b c d e f g h i j. Modify9 k k k k k k k k k k (a b c d e f g h i j) (In k ts) p b c d e f g h i j => t (a b c d e f g h i j)) (AllOf' k ts as t) 
data AllOf' k ts ((:) * (Octary k1 k2 k3 k4 k5 k6 k7 k8 k a p) as) = And8 (forall b c d e f g h i. Modify8 k k k k k k k k k (a b c d e f g h i) (In k ts) p b c d e f g h i => t (a b c d e f g h i)) (AllOf' k ts as t) 
data AllOf' k ts ((:) * (Septenary k1 k2 k3 k4 k5 k6 k7 k a p) as) = And7 (forall b c d e f g h. Modify7 k k k k k k k k (a b c d e f g h) (In k ts) p b c d e f g h => t (a b c d e f g h)) (AllOf' k ts as t) 
data AllOf' k ts ((:) * (Senary k1 k2 k3 k4 k5 k6 k a p) as) = And6 (forall b c d e f g. Modify6 k k k k k k k (a b c d e f g) (In k ts) p b c d e f g => t (a b c d e f g)) (AllOf' k ts as t) 
data AllOf' k ts ((:) * (Quinary k1 k2 k3 k4 k5 k a p) as) = And5 (forall b c d e f. Modify5 k k k k k k (a b c d e f) (In k ts) p b c d e f => t (a b c d e f)) (AllOf' k ts as t) 
data AllOf' k ts ((:) * (Quaternary k1 k2 k3 k4 k a p) as) = And4 (forall b c d e. Modify4 k k k k k (a b c d e) (In k ts) p b c d e => t (a b c d e)) (AllOf' k ts as t) 
data AllOf' k ts ((:) * (Ternary k1 k2 k3 k a p) as) = And3 (forall b c d. Modify3 k k k k (a b c d) (In k ts) p b c d => t (a b c d)) (AllOf' k ts as t) 
data AllOf' k ts ((:) * (Binary k1 k2 k a p) as) = And2 (forall b c. Modify2 k k k (a b c) (In k ts) p b c => t (a b c)) (AllOf' k ts as t) 
data AllOf' k ts ((:) * (Unary k1 k a p) as) = And1 (forall b. Modify k k (a b) (In k ts) p b => t (a b)) (AllOf' k ts as t) 
data AllOf' k ts ((:) * (AnyType k p) as) = AndAny (forall a. p a => t a) (AllOf' k ts as t) 
data AllOf' k ts ((:) * (Type k a) as) = And (t a) (AllOf' k ts as t) 

Constraint Combinators

Constraint combinators are used in the second parameter of <|, Unary, Binary, ..., or Denary. Note that each combinator is kind-polymorphic.

Basic Combinators

class (True ~ False) => This a Source

This creates a recursion. In other words, This will work as In as itself when used in the type list (first parameter) as of In, combined with Type, <|, Unary, Binary, ..., Denary, >+<, >++<, ..., >++++++++++<, >|<, >||<, ..., and >|||||||||<.

Note that This will not be expanded into In as if the condition described above is not satisfied. For example, This in the parameter of AnyType will not be expanded because it causes infinite recursion. Internally, the expansion is executed by Modify, Modify2, ..., and Modify10.

The instance of This itself cannot be created since the context True ~ False will never be satisfied.

There is no predetermined limit of recursion depth, but GHC has a fixed-depth recursion stack for safety, so you may need to increase the stack depth with -fcontext-stack=N.

class Pure a Source

Pure a is equivalent to the empty constraint ().

Pure a == ()

Instances

Pure k a 

type Is = (~) Source

(Is a) b == (a ~ b)

Combinators for Overlaying Contraints

class (p a, q a) => (p >+< q) a infixl 9 Source

(p >+< q) a == (p a, q a)

Instances

(p a, q a) => (>+<) k p q a 

class (p a b, q a b) => (p >++< q) a b infixl 9 Source

(p >++< q) a b == (p a b, q a b)

Instances

(p a b, q a b) => (>++<) k k p q a b 

class (p a b c, q a b c) => (p >+++< q) a b c infixl 9 Source

(p >+++< q) a b c == (p a b c, q a b c)

Instances

(p a b c, q a b c) => (>+++<) k k k p q a b c 

class (p a b c d, q a b c d) => (p >++++< q) a b c d infixl 9 Source

(p >++++< q) a b c d == (p a b c d, q a b c d)

Instances

(p a b c d, q a b c d) => (>++++<) k k k k p q a b c d 

class (p a b c d e, q a b c d e) => (p >+++++< q) a b c d e infixl 9 Source

(p >+++++< q) a b c d e == (p a b c d e, q a b c d e)

Instances

(p a b c d e, q a b c d e) => (>+++++<) k k k k k p q a b c d e 

class (p a b c d e f, q a b c d e f) => (p >++++++< q) a b c d e f infixl 9 Source

(p >++++++< q) a b c d e f == (p a b c d e f, q a b c d e f)

Instances

(p a b c d e f, q a b c d e f) => (>++++++<) k k k k k k p q a b c d e f 

class (p a b c d e f g, q a b c d e f g) => (p >+++++++< q) a b c d e f g infixl 9 Source

(p >+++++++< q) a b c d e f g == (p a b c d e f g, q a b c d e f g)

Instances

(p a b c d e f g, q a b c d e f g) => (>+++++++<) k k k k k k k p q a b c d e f g 

class (p a b c d e f g h, q a b c d e f g h) => (p >++++++++< q) a b c d e f g h infixl 9 Source

(p >++++++++< q) a b c d e f g h == (p a b c d e f g h, q a b c d e f g h)

Instances

(p a b c d e f g h, q a b c d e f g h) => (>++++++++<) k k k k k k k k p q a b c d e f g h 

class (p a b c d e f g h i, q a b c d e f g h i) => (p >+++++++++< q) a b c d e f g h i infixl 9 Source

(p >+++++++++< q) a b c d e f g h i == (p a b c d e f g h, q a b c d e f g h i)

Instances

(p a b c d e f g h i, q a b c d e f g h i) => (>+++++++++<) k k k k k k k k k p q a b c d e f g h i 

class (p a b c d e f g h i j, q a b c d e f g h i j) => (p >++++++++++< q) a b c d e f g h i j infixl 9 Source

(p >++++++++++< q) a b c d e f g h i j == (p a b c d e f g h, q a b c d e f g h i j)

Instances

(p a b c d e f g h i j, q a b c d e f g h i j) => (>++++++++++<) k k k k k k k k k k p q a b c d e f g h i j 

Combinators for Bonding Contraints

class (p a, q b) => (p >|< q) a b infixl 8 Source

(p >|< q) a b == (p a, q b)

Instances

(p a, q b) => (>|<) k k p q a b 

class (p a b, q c) => (p >||< q) a b c infixl 8 Source

(p >||< q) a b c == (p a b, q c)

Instances

(p a b, q c) => (>||<) k k k p q a b c 

class (p a b c, q d) => (p >|||< q) a b c d infixl 8 Source

(p >|||< q) a b c d == (p a b c, q d)

Instances

(p a b c, q d) => (>|||<) k k k k p q a b c d 

class (p a b c d, q e) => (p >||||< q) a b c d e infixl 8 Source

(p >||||< q) a b c d e == (p a b c d, q e)

Instances

(p a b c d, q e) => (>||||<) k k k k k p q a b c d e 

class (p a b c d e, q f) => (p >|||||< q) a b c d e f infixl 8 Source

(p >|||||< q) a b c d e f == (p a b c d e, q f)

Instances

(p a b c d e, q f) => (>|||||<) k k k k k k p q a b c d e f 

class (p a b c d e f, q g) => (p >||||||< q) a b c d e f g infixl 8 Source

(p >||||||< q) a b c d e f g == (p a b c d e f, q g)

Instances

(p a b c d e f, q g) => (>||||||<) k k k k k k k p q a b c d e f g 

class (p a b c d e f g, q h) => (p >|||||||< q) a b c d e f g h infixl 8 Source

(p >|||||||< q) a b c d e f g h == (p a b c d e f g, q h)

Instances

(p a b c d e f g, q h) => (>|||||||<) k k k k k k k k p q a b c d e f g h 

class (p a b c d e f g h, q i) => (p >||||||||< q) a b c d e f g h i infixl 8 Source

(p >||||||||< q) a b c d e f g h i == (p a b c d e f g h, q i)

Instances

(p a b c d e f g h, q i) => (>||||||||<) k k k k k k k k k p q a b c d e f g h i 

class (p a b c d e f g h i, q j) => (p >|||||||||< q) a b c d e f g h i j infixl 8 Source

(p >||||||||< q) a b c d e f g h i j == (p a b c d e f g h i, q j)

Instances

(p a b c d e f g h i, q j) => (>|||||||||<) k k k k k k k k k k p q a b c d e f g h i j 

Helpers

Helpers for Identical Constructors

type AllOfI as = AllOfI' as as Source

andI :: a -> AllOfI' ts as -> AllOfI' ts (Type a : as) infixr 0 Source

andI1 :: (forall b. Modify (a b) (In ts) p b => a b) -> AllOfI' ts as -> AllOfI' ts (Unary a p : as) infixr 0 Source

andI2 :: (forall b c. Modify2 (a b c) (In ts) p b c => a b c) -> AllOfI' ts as -> AllOfI' ts (Binary a p : as) infixr 0 Source

andI3 :: (forall b c d. Modify3 (a b c d) (In ts) p b c d => a b c d) -> AllOfI' ts as -> AllOfI' ts (Ternary a p : as) infixr 0 Source

andI4 :: (forall b c d e. Modify4 (a b c d e) (In ts) p b c d e => a b c d e) -> AllOfI' ts as -> AllOfI' ts (Quaternary a p : as) infixr 0 Source

andI5 :: (forall b c d e f. Modify5 (a b c d e f) (In ts) p b c d e f => a b c d e f) -> AllOfI' ts as -> AllOfI' ts (Quinary a p : as) infixr 0 Source

andI6 :: (forall b c d e f g. Modify6 (a b c d e f g) (In ts) p b c d e f g => a b c d e f g) -> AllOfI' ts as -> AllOfI' ts (Senary a p : as) infixr 0 Source

andI7 :: (forall b c d e f g h. Modify7 (a b c d e f g h) (In ts) p b c d e f g h => a b c d e f g h) -> AllOfI' ts as -> AllOfI' ts (Septenary a p : as) infixr 0 Source

andI8 :: (forall b c d e f g h i. Modify8 (a b c d e f g h i) (In ts) p b c d e f g h i => a b c d e f g h i) -> AllOfI' ts as -> AllOfI' ts (Octary a p : as) infixr 0 Source

andI9 :: (forall b c d e f g h i j. Modify9 (a b c d e f g h i j) (In ts) p b c d e f g h i j => a b c d e f g h i j) -> AllOfI' ts as -> AllOfI' ts (Nonary a p : as) infixr 0 Source

andI10 :: (forall b c d e f g h i j k. Modify10 (a b c d e f g h i j k) (In ts) p b c d e f g h i j k => a b c d e f g h i j k) -> AllOfI' ts as -> AllOfI' ts (Denary a p : as) infixr 0 Source

noneI :: AllOfI' ts [] Source

projI :: In as a => AllOfI as -> a Source

Helpers for Function Constructors

type AllOfF as t = AllOfF' as as t Source

andF :: (a -> t) -> AllOfF' ts as t -> AllOfF' ts (Type a : as) t infixr 0 Source

andF1 :: (forall b. Modify (a b) (In ts) p b => a b -> t) -> AllOfF' ts as t -> AllOfF' ts (Unary a p : as) t infixr 0 Source

andF2 :: (forall b c. Modify2 (a b c) (In ts) p b c => a b c -> t) -> AllOfF' ts as t -> AllOfF' ts (Binary a p : as) t infixr 0 Source

andF3 :: (forall b c d. Modify3 (a b c d) (In ts) p b c d => a b c d -> t) -> AllOfF' ts as t -> AllOfF' ts (Ternary a p : as) t infixr 0 Source

andF4 :: (forall b c d e. Modify4 (a b c d e) (In ts) p b c d e => a b c d e -> t) -> AllOfF' ts as t -> AllOfF' ts (Quaternary a p : as) t infixr 0 Source

andF5 :: (forall b c d e f. Modify5 (a b c d e f) (In ts) p b c d e f => a b c d e f -> t) -> AllOfF' ts as t -> AllOfF' ts (Quinary a p : as) t infixr 0 Source

andF6 :: (forall b c d e f g. Modify6 (a b c d e f g) (In ts) p b c d e f g => a b c d e f g -> t) -> AllOfF' ts as t -> AllOfF' ts (Senary a p : as) t infixr 0 Source

andF7 :: (forall b c d e f g h. Modify7 (a b c d e f g h) (In ts) p b c d e f g h => a b c d e f g h -> t) -> AllOfF' ts as t -> AllOfF' ts (Septenary a p : as) t infixr 0 Source

andF8 :: (forall b c d e f g h i. Modify8 (a b c d e f g h i) (In ts) p b c d e f g h i => a b c d e f g h i -> t) -> AllOfF' ts as t -> AllOfF' ts (Octary a p : as) t infixr 0 Source

andF9 :: (forall b c d e f g h i j. Modify9 (a b c d e f g h i j) (In ts) p b c d e f g h i j => a b c d e f g h i j -> t) -> AllOfF' ts as t -> AllOfF' ts (Nonary a p : as) t infixr 0 Source

andF10 :: (forall b c d e f g h i j k. Modify10 (a b c d e f g h i j k) (In ts) p b c d e f g h i j k => a b c d e f g h i j k -> t) -> AllOfF' ts as t -> AllOfF' ts (Denary a p : as) t infixr 0 Source

noneF :: AllOfF' ts [] t Source

projF :: In as a => AllOfF as t -> a -> t Source

Examples

Example1: Hello

Let's begin with a basic example.

type Hellos = [
    Type String,
    Type Int,
    Type Double,
    Unary [] Show,
    Quaternary (,,,) (This >|< This >||< This >|||< This)]
hello :: In Hellos a => a -> String
hello = projF (
    (\s -> "hello, " ++ s) `andF`
    (\n -> "Mr. " ++ show n) `andF`
    (\x -> show (x / 2) ++ " times two") `andF`
    (\xs -> concatMap ((++", ") . show) xs ++ "period") `andF1`
    (\(x,y,z,w) ->
        hello x ++ " and " ++ hello y ++ " and " ++
        hello z ++ " and " ++ hello w) `andF4`
    noneF :: AllOfF Hellos String)

main = putStrLn $
    hello ("world", 42 :: Int, 3.14 :: Double, [True, False])

This is the result.

hello, world and Mr. 42 and 1.57 times two and True, False, period

Example2: Printf

With a recursive cluss, you can easily make a function that can take a variable number of arguments. The function below is a simplified C-style printf.

type Printfs = [Binary (->) (Show >|< This), Type String]
printf :: In Printfs a => String -> a
printf s = projI (
    (\x -> printf (go s (show x))) `andI2`
    s `andI`
    noneI :: AllOfI Printfs)
  where
    go ('@' : cs) t = t ++ cs
    go (c : cs) t = c : go cs t
    go [] _ = error "there is no '@' any more!"

main = putStrLn $
    printf "@ good @ and @" 12 "men" True

This is the result.

12 good "men" and True

Example3: Monad

Here is a more complex example. When the type of a "cluss method" is complex, you generally have to create newtypes (like Bind and Return below).

type Monads = [Type [], Unary (->) Pure, Unary (,) Monoid, Unary Wrap This]
newtype Wrap m a = Wrap {unWrap :: m a}
newtype Bind a b m = Bind {unBind :: m a -> (a -> m b) -> m b}
newtype Return a m = Return {unReturn :: a -> m a}
bind :: In Monads m => m a -> (a -> m b) -> m b
bind = unBind $ proj (
    Bind (\m k -> concatMap k m) `And`
    Bind (\m k e -> k (m e) e) `And1`
    Bind (\(a,x) k -> let (a2,x2) = k x in (a<>a2,x2)) `And1`
    Bind (\m k -> Wrap (unWrap m `bind` (unWrap . k))) `And1`
    None :: AllOf Monads (Bind a b))
return' :: In Monads m => a -> m a
return' = unReturn $ proj (
    Return (: []) `And`
    Return const `And1`
    Return ((,) mempty) `And1`
    Return (Wrap . return') `And1`
    None :: AllOf Monads (Return a))
infixl 1 `bind`

main = print $
    return' 1 `bind` replicate 3 `bind` (\n -> [n .. n+4])

This is the result.

[1,2,3,4,5,1,2,3,4,5,1,2,3,4,5]