David Menendez wrote:
Joachim Breitner wrote:
today while mowing the lawn, I thought how to statically prevent some
problems with infinte lists. I was wondering if it is possible to
somehow mark a list as one of finite/infinite/unknown and to mark
list-processing functions as whether they can handle infinte lists.

One possibility would be to have some phantom markers in the list
type. For example,

newtype List isEmpty isFinite a = MarkList [a]

data Finite
data Infinite
data Empty
data Nonempty
data Unknown

Yes, phantom types are what Joachim wants. For more about phantom types, see also

  http://haskell.org/haskellwiki/Phantom_type

  Ralf Hinze. Fun with Phantom Types.
  http://www.informatik.uni-bonn.de/~ralf/publications/With.pdf

Another possibility for working with infinite lists would be a new data type

  data InfList a = a :> InfList a

(also called Stream but this name is quite overloaded.)

cons    :: a -> List e f a -> List Nonempty f a

But unfortunately, finiteness is a special property that the type system cannot guarantee. The above type signature for cons doesn't work since the following would type check

  bad :: a -> List Nonempty Finite a
  bad x = let xs = cons x xs in xs

In other words, Haskell's type system doesn't detect infinite recursion. (But there are type systems like System F or that of Epigram that disallow general recursion.)


As a variation, we can use rank-2 types instead of Unknown; e.g.

tail   :: List Nonempty f a -> (forall e. List e f a -> w) -> w
filter :: (a -> Bool) -> List e f a -> (forall e. List e f a -> w) -> w

That's probably best explained in terms of the existential quantor

 tail   :: List Nonempty f a -> (exists e. List e f a)
 filter :: (a -> Bool) -> List e f a -> (exists e. List e f a)

In other words, tail takes a nonempty list and returns one that has an "emptiness" e but that's all we know. Existential quantification is not first-class in Haskell, so you can either use a data type

 data Box100 f b c = forall a . Box100 (f a b c)

 tail :: List Nonempty f a -> Box100 List f a

or encode it via the isomorphism

 exists e . expr e = forall w . (forall e . expr e -> w) -> w


Regards,
apfelmus

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to