--
Jason Dusek
Linux User #510144 | http://counter.li.org/
_______________________________________________
Haskell-Cafe mailing list
Haskel...@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
The code below typechecks, though actually it shouldn't: there's no
type "n" such that "ones" is formed by the FL from some value of type
List Int n.
Or should it?
{-# LANGUAGE ExistentialQuantification, GADTs, EmptyDataDecls #-}
module Finite where
data Zero
data Succ a
class Finite a where
instance Finite Zero
instance (Finite a) => Finite (Succ a)
data List a n where
Nil :: List a Zero
Cons :: (Finite n) => a -> List a n -> List a (Succ n)
data FiniteList a where
FL :: (Finite n) => List a n -> FiniteList a
nil :: FiniteList a
nil = FL Nil
cons :: a -> FiniteList a -> FiniteList a
cons a (FL x) = FL (Cons a x)
list123 = cons 1 (cons 2 (cons 3 nil))
ones = cons 1 ones -- typechecks ok
2010/10/13 Jason Dusek <jason...@gmail.com>:
--
Eugene Kirpichov
Senior Software Engineer,
Grid Dynamics http://www.griddynamics.com/
Maybe you want a list whose denotation is formed by a least (rather
than a greatest) fixed point? i.e. the type of spine-strict lists:
"""
data FinList a = Nil
| Cons a !(FinList a)
deriving (Show)
ones_fin = 1 `Cons` ones_fin
take_fin n Nil = Nil
take_fin n (Cons x rest)
| n <= 0 = Nil
| otherwise = Cons x (take_fin (n - 1) rest)
ones = 1 : ones
main = do
print $ take 5 ones
print $ take_fin 5 ones_fin
"""
If you have e :: FinList a then if e /= _|_ it is necessarily of finite length.
Max
hd :: FiniteList a -> Maybe a
hd (FL as) = hdList as
*Finite> hd ones
this hangs, so, my guess is that ones = _|_
13.10.2010 12:13, Eugene Kirpichov пишет:
> {-# LANGUAGE ExistentialQuantification, GADTs, EmptyDataDecls #-}
> module Finite where
>
> data Zero
> data Succ a
>
> class Finite a where
>
> instance Finite Zero
> instance (Finite a) => Finite (Succ a)
>
> data List a n where
> Nil :: List a Zero
> Cons :: (Finite n) => a -> List a n -> List a (Succ n)
>
> data FiniteList a where
> FL :: (Finite n) => List a n -> FiniteList a
>
> nil :: FiniteList a
> nil = FL Nil
>
> cons :: a -> FiniteList a -> FiniteList a
> cons a (FL x) = FL (Cons a x)
>
> list123 = cons 1 (cons 2 (cons 3 nil))
>
> ones = cons 1 ones -- typechecks ok
2010/10/13 Miguel Mitrofanov <migue...@yandex.ru>:
--
Eugene Kirpichov
Senior Software Engineer,
Grid Dynamics http://www.griddynamics.com/
13.10.2010 12:33, Eugene Kirpichov О©╫О©╫О©╫О©╫О©╫:
> Well, it's easy to make it so that lists are either finite or bottom,
> but it's not so easy to make infinite lists fail to typecheck...
> That's what I'm wondering about.
>
> 2010/10/13 Miguel Mitrofanov<migue...@yandex.ru>:
>> hdList :: List a n -> Maybe a
>> hdList Nil = Nothing
>> hdList (Cons a _) = Just a
>>
>> hd :: FiniteList a -> Maybe a
>> hd (FL as) = hdList as
>>
>> *Finite> hd ones
>>
>> this hangs, so, my guess is that ones = _|_
>>
>>
>> 13.10.2010 12:13, Eugene Kirpichov О©╫О©╫О©╫О©╫О©╫:
13 октября 2010 г. 12:37 пользователь Miguel Mitrofanov
<migue...@yandex.ru> написал:
> So... you want your "ones" not to typecheck? Guess that's impossible, since
> it's nothing but "fix" application...
>
> 13.10.2010 12:33, Eugene Kirpichov пишет:
>>
>> Well, it's easy to make it so that lists are either finite or bottom,
>> but it's not so easy to make infinite lists fail to typecheck...
>> That's what I'm wondering about.
>>
>> 2010/10/13 Miguel Mitrofanov<migue...@yandex.ru>:
>>>
>>> hdList :: List a n -> Maybe a
>>> hdList Nil = Nothing
>>> hdList (Cons a _) = Just a
>>>
>>> hd :: FiniteList a -> Maybe a
>>> hd (FL as) = hdList as
>>>
>>> *Finite> hd ones
>>>
>>> this hangs, so, my guess is that ones = _|_
>>>
>>>
>>> 13.10.2010 12:13, Eugene Kirpichov пишет:
>>>>
>>>> {-# LANGUAGE ExistentialQuantification, GADTs, EmptyDataDecls #-}
>>>> module Finite where
>>>>
>>>> data Zero
>>>> data Succ a
>>>>
>>>> class Finite a where
>>>>
>>>> instance Finite Zero
>>>> instance (Finite a) => Finite (Succ a)
>>>>
>>>> data List a n where
>>>> Nil :: List a Zero
>>>> Cons :: (Finite n) => a -> List a n -> List a (Succ n)
>>>>
>>>> data FiniteList a where
>>>> FL :: (Finite n) => List a n -> FiniteList a
>>>>
>>>> nil :: FiniteList a
>>>> nil = FL Nil
>>>>
>>>> cons :: a -> FiniteList a -> FiniteList a
>>>> cons a (FL x) = FL (Cons a x)
>>>>
>>>> list123 = cons 1 (cons 2 (cons 3 nil))
>>>>
>>>> ones = cons 1 ones -- typechecks ok
>>>
>>> _______________________________________________
>>> Haskell-Cafe mailing list
>>> Haskel...@haskell.org
>>> http://www.haskell.org/mailman/listinfo/haskell-cafe
>>>
>>
>>
>
--
Eugene Kirpichov
Senior Software Engineer,
Grid Dynamics http://www.griddynamics.com/
http://hpaste.org/40535/finite_list_with_fundeps
(This is rather a draft. If anyone can help me out with the TODOs, I'd be happy.)
-- Steffen
On 10/13/2010 10:40 AM, Eugene Kirpichov wrote:
> Well, in my implementation it's indeed impossible. It might be
> possible in another one. That is the question :)
> Perhaps we'll have to change the type of cons, or something.
>
> 13 О©╫О©╫О©╫О©╫О©╫О©╫О©╫ 2010 О©╫. 12:37 О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ Miguel Mitrofanov
> <migue...@yandex.ru> О©╫О©╫О©╫О©╫О©╫О©╫О©╫:
>> So... you want your "ones" not to typecheck? Guess that's impossible, since
>> it's nothing but "fix" application...
>>
>> 13.10.2010 12:33, Eugene Kirpichov О©╫О©╫О©╫О©╫О©╫:
>>>
>>> Well, it's easy to make it so that lists are either finite or bottom,
>>> but it's not so easy to make infinite lists fail to typecheck...
>>> That's what I'm wondering about.
>>>
>>> 2010/10/13 Miguel Mitrofanov<migue...@yandex.ru>:
>>>>
>>>> hdList :: List a n -> Maybe a
>>>> hdList Nil = Nothing
>>>> hdList (Cons a _) = Just a
>>>>
>>>> hd :: FiniteList a -> Maybe a
>>>> hd (FL as) = hdList as
>>>>
>>>> *Finite> hd ones
>>>>
>>>> this hangs, so, my guess is that ones = _|_
>>>>
>>>>
>>>> 13.10.2010 12:13, Eugene Kirpichov О©╫О©╫О©╫О©╫О©╫:
Sad thing.
[1] http://hpaste.org/40538/finite_list__not_as_easy_as_i
On 10/13/2010 03:27 PM, Eugene Kirpichov wrote:
> Again, the question is not how to arrange that all non-bottom values
> are finite: this can easily be done using strictness, as in your List
> example.
>
> The trick is to reject infinite values in compile time. How can *this* be done?
>
> 13 О©╫О©╫О©╫О©╫О©╫О©╫О©╫ 2010 О©╫. 15:26 О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ Permjacov Evgeniy
> <perm...@gmail.com> О©╫О©╫О©╫О©╫О©╫О©╫О©╫:
>> On 10/13/2010 03:09 PM, Eugene Kirpichov wrote:
>>
>> 1-st scenario: If you have, for example, 2-3 tree, it definitly has a
>> root. If you construct tree from list and then match over root, the
>> entire tree (and entire source list) will be forced. And on every
>> update, 2-3 tree's root is reconstructed in functional setting. So, if
>> you'll try to build 2-3 tree from infinite list, it will fail in process
>> due insuffisient memory.
>> Of course, you can make the same with
>> data List a = Cons a (!List a) | Nil
>>
>> second scenario
>> data Node a = Nil | One a | Two a a
>> and so Node (Node (Node (Node a))) has at most 2^4 = 16 elements. with
>> some triks you'll be able to set upper bound in runtime.
>>
>>> I don't see how. Could you elaborate?
>>>
>>> 13 О©╫О©╫О©╫О©╫О©╫О©╫О©╫ 2010 О©╫. 14:46 О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ Permjacov Evgeniy
>>> <perm...@gmail.com> О©╫О©╫О©╫О©╫О©╫О©╫О©╫:
>>>> On 10/13/2010 12:33 PM, Eugene Kirpichov wrote:
>>>> I think, tree-like structure, used as sequence (like fingertrees), will
>>>> do the work.
>>>>> but it's not so easy to make infinite lists fail to typecheck...
>>>>> That's what I'm wondering about.
>>>>>
>>>>> 2010/10/13 Miguel Mitrofanov <migue...@yandex.ru>:
>>>>>> hdList :: List a n -> Maybe a
>>>>>> hdList Nil = Nothing
>>>>>> hdList (Cons a _) = Just a
>>>>>>
>>>>>> hd :: FiniteList a -> Maybe a
>>>>>> hd (FL as) = hdList as
>>>>>>
>>>>>> *Finite> hd ones
>>>>>>
>>>>>> this hangs, so, my guess is that ones = _|_
>>>>>>
>>>>>>
>>>>>> 13.10.2010 12:13, Eugene Kirpichov О©╫О©╫О©╫О©╫О©╫:
Nice, but how about a list destructor?
;-)
(++) :: Finite s1 a -> Finite s2 a -> Finite (S (Plus s1 s2)) a
(++) (Finite a) (Finite b) = Finite $ a Prelude.++ b
infixr 5 ++
Fascinating. Doing
ones' = Cons 1 ones'
of course does not typecheck (as expected) with an occurs check error
(can't unify n = S n). But
ones = cons 1 ones
does typecheck. And it makes sense: I can see why cons has the type
it does, and given that type for cons this definition of ones is
perfectly well-typed. But the upshot, which I had never considered,
seems to be that existentially quantified types are allowed to be _|_.
-Brent
Thanks - I was meaning an equivalent to viewl on Data.Sequence, on plain lists:
viewl :: [a] -> Either () (a,[a])
viewl [] = Left ()
viewl (x:xs) = Right (x,xs)
It was a trick question because I can't see how you can do it without
decrement on the Peano numbers.
Best wishes
Stephen
Hi Stephen,
Thanks - I was anticipating a type like this for the destructor:
viewl :: Finite s a -> Either () (a, Finite (Predecessor s) a)
I didn't appreciate that the size type in your code represented the
upper bound and not the actual size.
--
Jason Dusek
Linux User #510144 | http://counter.li.org/
Indeed. Where I said "is necessarily" I meant "is not necessarily".