... | ... | @@ -10,28 +10,16 @@ implementation of the GHC extension for overloading Haskell's list notation. |
|
|
Let us briefly recap the notation for constructing lists. In Haskell, the list
|
|
|
notation can be be used in the following seven ways:
|
|
|
|
|
|
```wiki
|
|
|
[] -- Empty list
|
|
|
[x] -- x : []
|
|
|
[x,y,z] -- x : y : z : []
|
|
|
[x .. ] -- enumFrom x
|
|
|
[x,y ..] -- enumFromThen x y
|
|
|
[x .. y] -- enumFromTo x y
|
|
|
[x,y .. z] -- enumFromThenTo x y z
|
|
|
```
|
|
|
[]-- Empty list[x]-- x : [][x,y,z]-- x : y : z : [][x ..]-- enumFrom x[x,y ..]-- enumFromThen x y[x .. y]-- enumFromTo x y[x,y .. z]-- enumFromThenTo x y z
|
|
|
```
|
|
|
|
|
|
|
|
|
When the `OverloadedLists` extension is turned on, the aforementioned seven
|
|
|
notations are desugared as follows:
|
|
|
|
|
|
```wiki
|
|
|
[] -- fromListN 0 []
|
|
|
[x] -- fromListN 1 (x : [])
|
|
|
[x,y,z] -- fromListN 3 (x : y : z : [])
|
|
|
[x .. ] -- fromList (enumFrom x)
|
|
|
[x,y ..] -- fromList (enumFromThen x y)
|
|
|
[x .. y] -- fromList (enumFromTo x y)
|
|
|
[x,y .. z] -- fromList (enumFromThenTo x y z)
|
|
|
```
|
|
|
[]-- fromListN 0 [][x]-- fromListN 1 (x : [])[x,y,z]-- fromListN 3 (x : y : z : [])[x ..]-- fromList (enumFrom x)[x,y ..]-- fromList (enumFromThen x y)[x .. y]-- fromList (enumFromTo x y)[x,y .. z]-- fromList (enumFromThenTo x y z)
|
|
|
```
|
|
|
|
|
|
|
... | ... | @@ -39,28 +27,23 @@ This extension allows programmers to use the list notation for construction of |
|
|
structures like: `Set`, `Map`, `IntMap`, `Vector`, `Text`
|
|
|
and `Array`. The following code listing gives a few examples:
|
|
|
|
|
|
```wiki
|
|
|
['0' .. '9'] :: Set Char
|
|
|
[1 .. 10] :: Vector Int
|
|
|
[("default",0), (k1,v1)] :: Map String Int
|
|
|
['a' .. 'z'] :: Text
|
|
|
```
|
|
|
['0'..'9']::SetChar[1..10]::VectorInt[("default",0),(k1,v1)]::MapStringInt['a'..'z']::Text
|
|
|
```
|
|
|
|
|
|
|
|
|
List patterns are also overloaded. When the `OverloadedLists` extension is turned on, the
|
|
|
definitions
|
|
|
|
|
|
```wiki
|
|
|
f [] = ...
|
|
|
g [x,y,z] = ...
|
|
|
```
|
|
|
f[]=...g[x,y,z]=...
|
|
|
```
|
|
|
|
|
|
|
|
|
will be treated as
|
|
|
|
|
|
```wiki
|
|
|
f (toList -> []) = ...
|
|
|
g (toList -> [x,y,z]) = ...
|
|
|
```
|
|
|
f(toList ->[])=...g(toList ->[x,y,z])=...
|
|
|
```
|
|
|
|
|
|
|
... | ... | @@ -73,9 +56,8 @@ That said, the `GHC.Exts` module exports the `IsList` class that can |
|
|
be used to overload `fromListN` and `fromListN` for different
|
|
|
structures. The type class is defined as follows:
|
|
|
|
|
|
```wiki
|
|
|
class IsList l where
|
|
|
type Item l
|
|
|
```
|
|
|
classIsList l wheretypeItem l
|
|
|
fromList ::[Item l]-> l
|
|
|
toList :: l ->[Item l]
|
|
|
|
... | ... | @@ -98,7 +80,7 @@ behaviour of `fromListN` is not specified. |
|
|
The instances of the `IsList` class should satisfy the following
|
|
|
property:
|
|
|
|
|
|
```wiki
|
|
|
```
|
|
|
fromList. toList = id
|
|
|
```
|
|
|
|
... | ... | @@ -106,34 +88,28 @@ fromList . toList = id |
|
|
In the following, we give several example instances of the `IsList` type
|
|
|
class:
|
|
|
|
|
|
```wiki
|
|
|
instance IsList [a] where
|
|
|
type Item [a] = a
|
|
|
```
|
|
|
instanceIsList[a]wheretypeItem[a]= a
|
|
|
fromList = id
|
|
|
toList = id
|
|
|
|
|
|
instance (Ord a) => IsList (Set a) where
|
|
|
type Item (Set a) = a
|
|
|
instance(Ord a)=>IsList(Set a)wheretypeItem(Set a)= a
|
|
|
fromList =Set.fromList
|
|
|
toList =Set.toList
|
|
|
|
|
|
instance (Ord k) => IsList (Map k v) where
|
|
|
type Item (Map k v) = (k,v)
|
|
|
instance(Ord k)=>IsList(Map k v)wheretypeItem(Map k v)=(k,v)
|
|
|
fromList =Map.fromList
|
|
|
toList =Map.toList
|
|
|
|
|
|
instance IsList (IntMap v) where
|
|
|
type Item (IntMap v) = (Int,v)
|
|
|
instanceIsList(IntMap v)wheretypeItem(IntMap v)=(Int,v)
|
|
|
fromList =IntMap.fromList
|
|
|
toList =IntMap.toList
|
|
|
|
|
|
instance IsList Text where
|
|
|
type Item Text = Char
|
|
|
instanceIsListTextwheretypeItemText=Char
|
|
|
fromList =Text.pack
|
|
|
toList =Text.unpack
|
|
|
|
|
|
instance IsList (Vector a) where
|
|
|
type Item (Vector a) = a
|
|
|
instanceIsList(Vector a)wheretypeItem(Vector a)= a
|
|
|
fromList =Vector.fromList
|
|
|
toList =Vector.toList
|
|
|
fromListN =Vector.fromListN
|
... | ... | @@ -175,11 +151,21 @@ http://www.mail-archive.com/haskell-cafe@haskell.org/msg101412.html |
|
|
|
|
|
The `OverloadedLists` extension as, implemented above, would not be able to be used on heterogeneous lists, for example, as implemented below:
|
|
|
|
|
|
```wiki
|
|
|
data HList :: [*] -> * where
|
|
|
HNil :: HList '[]
|
|
|
HCons :: a -> HList xs -> HList (a ': xs)
|
|
|
```
|
|
|
dataHList::[*]->*whereHNil::HList'[]HCons:: a ->HList xs ->HList(a ': xs)
|
|
|
```
|
|
|
|
|
|
|
|
|
This is a bit disappointing. However, I'm not really sure how you could make this extension support this use case, even if you added some hacks to the `IsList` class.
|
|
|
|
|
|
## Length-{indexed,observed} Vectors
|
|
|
|
|
|
|
|
|
The current extension can't be used to represent list literals for length-indexed vectors as e.g.
|
|
|
|
|
|
```
|
|
|
-- (alternatively, GHC.TypeLits.Nat)dataNat=Ze|SuNatdataVec::*->Nat->*whereNil::Vec a ZeCons:: a ->Vec a n ->Vec a (Su n)
|
|
|
```
|
|
|
|
|
|
|
|
|
as the length-information is not provided in a suitable way. |