In Haskell, it is said that any ADT can be expressed as sum of products. I'm trying to find a flat type that is isomorphic to Tree
, on Data.Tree
.
Tree a = Node a [Tree a] -- has a nested type (List!)
I want to write a functionally identical definition for Tree without nested types:
Tree = ??? -- no nested types allowed
For that, I tried writing the recursive relation for the type algebras:
L a = 1 + a * L a
T a = a * L (T a)
Inlining L, I had:
T a = a * (1 + T a * L (T a))
T a = a * (1 * T a * (1 + T a * L (T a)))
T a = a * (1 + T a * (1 + T a * (1 + T a * L (T a))))
That wasn't going anywhere, so I stopped and did the multiplications, leaving me with:
T a = a + a * T a + a * T a * T a ...
Which is the same as:
T a = a * (T a) ^ 0 + a * (T a) ^ 1 + a * (T a) ^ 2 ...
That is a sum of products, but it is infinite. I can't write that in Haskell. By abusing the algebra:
(T a) - (T a) ^ 2 = a * T a
- (T a) ^ 2 - a * T a + (T a) = 0
Solving for T a
, I found that:
T a = 1 - a
Which obviously doesn't make any sense. So, back to the original question: how do I flatten Tree
from Data.Tree
so I can write a type that is isomorphic to it without nested types?
This question isn't a duplicate of my previous question. The last one is about representing nested types with the Scott Encoding, for which the correct answer is "ignore the nesting". This one proceeds to ask how to flatten a nested type anyway (since it is needed for a particular use of the Scott Encoding, but not obligatory in general).
data Rec a = A a (Rec a) | B a a a a | C a (Rec a) a | D a
, is perfectly valid. But recursion on another recursive procedure (such as the[Tree a]
here) isn't OK. I want that specifically because I'm encoding Haskell datatypes on the Lambda Calculus using the Scott Encoding, which doesn't account for nested types, so I have to somehow do it without nesting. – MaiaVictorTree
doesn't seem problematic to me, for Scott encoding. Shouldn't this work? – András Kovács(head tail cons nil → cons cons nil head tail)
instead of(head tail cons nil → cons head tail)
. Using that, I'm able to derive a normalizingfold
for any datatype generically by representing them asScott :: [[Field]]
, where(Field :: Bool) == true if the field is recursive
. That way, List is represented as[[false true] []]
, for example. Not sure it is the only way. Any idea? – MaiaVictor