Comments on: Towards Formal Power Series for Functors http://comonad.com/reader/2008/towards-formal-power-series-for-functors/ types, (co)monads, substructural logic Sat, 29 Dec 2012 15:18:06 -0800 http://wordpress.org/?v=2.8.4 hourly 1 By: The Comonad.Reader » Generatingfunctorology http://comonad.com/reader/2008/towards-formal-power-series-for-functors/comment-page-1/#comment-1295 The Comonad.Reader » Generatingfunctorology Wed, 14 May 2008 07:45:48 +0000 http://comonad.com/reader/2008/towards-formal-power-series-for-functors/#comment-1295 [...] Ok, I decided to take a step back from my flawed approach in the last post and play with the idea of power series of functors from a different perspective. [...] [...] Ok, I decided to take a step back from my flawed approach in the last post and play with the idea of power series of functors from a different perspective. [...]

]]>
By: Edward Kmett http://comonad.com/reader/2008/towards-formal-power-series-for-functors/comment-page-1/#comment-1289 Edward Kmett Wed, 14 May 2008 01:41:09 +0000 http://comonad.com/reader/2008/towards-formal-power-series-for-functors/#comment-1289 Hrmm, So a simple encoding of the basic AD rules leaves your Dual class, just one level up. data D f g a = D (f a) (g a) type family (:+>) (f :: * -> *) (g :: * -> *) :: * -> * type family (:*>) (f :: * -> *) (g :: * -> *) :: * -> * type family DLift (f :: (* -> *) -> * -> *) (f' :: (* -> *) -> * -> *) (g :: * -> *) :: * -> * type instance (D x a :+> D y b) = D (x :+: y) (a :+: b) type instance (D x a :*> D y b) = D (x :*: y) (x :*: b :+: a :*: y) type instance DLift f f' (D x a) = D (f x) (a :+: f' x) dConst :: a -> D Identity Zero a dConst z = D (Identity z) zero dVar :: a -> D Identity One a dVar z = D (Identity z) (suck zero) I think the general AD case requires polymorphic kinds, so yeah something like Omega is probably better suited. Alas. Hrmm,

So a simple encoding of the basic AD rules leaves your Dual class, just one level up.

data D f g a = D (f a) (g a)

type family (:+>) (f :: * -> *) (g :: * -> *) :: * -> *
type family (:*>) (f :: * -> *) (g :: * -> *) :: * -> *
type family DLift (f :: (* -> *) -> * -> *) (f’ :: (* -> *) -> * -> *) (g :: * -> *) :: * -> *
type instance (D x a :+> D y b) = D (x :+: y) (a :+: b)
type instance (D x a :*> D y b) = D (x :*: y) (x :*: b :+: a :*: y)
type instance DLift f f’ (D x a) = D (f x) (a :+: f’ x)

dConst :: a -> D Identity Zero a
dConst z = D (Identity z) zero

dVar :: a -> D Identity One a
dVar z = D (Identity z) (suck zero)

I think the general AD case requires polymorphic kinds, so yeah something like Omega is probably better suited. Alas.

]]>
By: Edward Kmett http://comonad.com/reader/2008/towards-formal-power-series-for-functors/comment-page-1/#comment-1288 Edward Kmett Wed, 14 May 2008 01:04:55 +0000 http://comonad.com/reader/2008/towards-formal-power-series-for-functors/#comment-1288 Yeah, mostly i was just trying to see what an inductive family of types built over an open type function would look like. I left the fixed point cases off because I was still trying to get the finite cases to terminate and once I ran up against the wall of type-ability I didn't check that what I had so far was what I thought I had so far. It has been a while since I did anything with classical analysis. Hrmm. Back to the drawing board I guess until I figure out how to do what I really want. Yeah, mostly i was just trying to see what an inductive family of types built over an open type function would look like.

I left the fixed point cases off because I was still trying to get the finite cases to terminate and once I ran up against the wall of type-ability I didn’t check that what I had so far was what I thought I had so far.

It has been a while since I did anything with classical analysis. Hrmm. Back to the drawing board I guess until I figure out how to do what I really want.

]]>
By: sigfpe http://comonad.com/reader/2008/towards-formal-power-series-for-functors/comment-page-1/#comment-1286 sigfpe Wed, 14 May 2008 00:14:12 +0000 http://comonad.com/reader/2008/towards-formal-power-series-for-functors/#comment-1286 Oh yeah, I almost forgot. Check out Conor McBride et al's handling of derivatives <a href="http://strictlypositive.org/Holes.pdf" rel="nofollow">here</a>. It includes the handling of fixed points. Oh yeah, I almost forgot. Check out Conor McBride et al’s handling of derivatives here. It includes the handling of fixed points.

]]>
By: sigfpe http://comonad.com/reader/2008/towards-formal-power-series-for-functors/comment-page-1/#comment-1285 sigfpe Wed, 14 May 2008 00:10:12 +0000 http://comonad.com/reader/2008/towards-formal-power-series-for-functors/#comment-1285 I'm confused. This doesn't look like AD to me. The rules you give are the standard Leibniz rules for symbolic differentiation and then I think you're trying to use those to get a (compile time) list of all derivatives. This is a really neat thing to attempt (though I have a hunch it's not possible in Haskell) but it seems quite different to AD to me. Anyway, I suspect a language like Omega may be better suited for what you are doing. I’m confused. This doesn’t look like AD to me. The rules you give are the standard Leibniz rules for symbolic differentiation and then I think you’re trying to use those to get a (compile time) list of all derivatives. This is a really neat thing to attempt (though I have a hunch it’s not possible in Haskell) but it seems quite different to AD to me. Anyway, I suspect a language like Omega may be better suited for what you are doing.

]]>
By: apfelmus http://comonad.com/reader/2008/towards-formal-power-series-for-functors/comment-page-1/#comment-1282 apfelmus Tue, 13 May 2008 20:30:53 +0000 http://comonad.com/reader/2008/towards-formal-power-series-for-functors/#comment-1282 Concerning the division, we can appeal to the special case <code> a^n / n! = Bag n a</code> i.e. the multiset (bag) with n elements of type a. So, the power series expansion for a data type just counts how many different sets of elements it may contain. So, <code>a :*: a</code> contains two bags of two a (one for each permutation in the tuple). Btw, as the differential equation for the list type suggests, we have the power series expansion <code> [a] = 1 + a + a^2 + a^3 + ... </code> which "is" 1/(1-a). Concerning the division, we can appeal to the special case

a^n / n! = Bag n a

i.e. the multiset (bag) with n elements of type a. So, the power series expansion for a data type just counts how many different sets of elements it may contain. So, a :*: a contains two bags of two a (one for each permutation in the tuple).

Btw, as the differential equation for the list type suggests, we have the power series expansion
[a] = 1 + a + a^2 + a^3 + ...
which “is” 1/(1-a).

]]>
By: Dan Doel http://comonad.com/reader/2008/towards-formal-power-series-for-functors/comment-page-1/#comment-1280 Dan Doel Tue, 13 May 2008 20:21:07 +0000 http://comonad.com/reader/2008/towards-formal-power-series-for-functors/#comment-1280 Although the context on Functor (AD f) is sufficient, it seems (to me) like the wrong place to specify it. Since AD f a ~~ (f a, AD (D f) a) With (Derivable f) => Functor (AD f) you only need (Derivable (D f)) to justify using bimap (fmap f) (fmap f). So, it seems like what you'd really want is: class (Functor f, Derivable (D f)) => Derivable f where type D f :: * -> * instance (Derivable f) => Functor (AD f) where ... Where the context on Derivable enforces that all such functors are arbitrarily differentiable. But, of course, GHC complains about a cycle there (in 6.8, at least. I don't have 6.9 handy). Simplification should, I think, be possible with total type families once they go into 6.9. For instance: type family (f :: * -> *) :+: (g :: * -> *) :: * -> * where Zero :+: g = g f :+: Zero = f f :+: g = Lift Either f g You're allowed to overlap instances for total type families, because they're closed. Although the context on Functor (AD f) is sufficient, it seems (to me) like the wrong place to specify it. Since

AD f a ~~ (f a, AD (D f) a)

With (Derivable f) => Functor (AD f) you only need (Derivable (D f)) to justify using bimap (fmap f) (fmap f). So, it seems like what you’d really want is:

class (Functor f, Derivable (D f)) => Derivable f where
type D f :: * -> *

instance (Derivable f) => Functor (AD f) where …

Where the context on Derivable enforces that all such functors are arbitrarily differentiable. But, of course, GHC complains about a cycle there (in 6.8, at least. I don’t have 6.9 handy).

Simplification should, I think, be possible with total type families once they go into 6.9. For instance:

type family (f :: * -> *) :+: (g :: * -> *) :: * -> * where
Zero :+: g = g
f :+: Zero = f
f :+: g = Lift Either f g

You’re allowed to overlap instances for total type families, because they’re closed.

]]>
By: Edward Kmett http://comonad.com/reader/2008/towards-formal-power-series-for-functors/comment-page-1/#comment-1278 Edward Kmett Tue, 13 May 2008 16:43:08 +0000 http://comonad.com/reader/2008/towards-formal-power-series-for-functors/#comment-1278 Oh, maybe a more interesting instance for this would probably be the notion of a derivative for a list since that doesn't zero out: instance Derivable [] where type D [] = [] :*: [] I also would like to find out a way to include a simplification step in the type function to go through and do the Zero :*: x = Zero step, etc to make the encoding a little less naive. Oh, maybe a more interesting instance for this would probably be the notion of a derivative for a list since that doesn’t zero out:

instance Derivable [] where
type D [] = [] :*: []

I also would like to find out a way to include a simplification step in the type function to go through and do the Zero :*: x = Zero step, etc to make the encoding a little less naive.

]]>
By: Edward Kmett http://comonad.com/reader/2008/towards-formal-power-series-for-functors/comment-page-1/#comment-1277 Edward Kmett Tue, 13 May 2008 16:32:36 +0000 http://comonad.com/reader/2008/towards-formal-power-series-for-functors/#comment-1277 True enough. I just started down this path because I was thinking in terms of inductive families of types, and realized with open type functions that you could put a more interesting operation in than just a pair, etc. And yeah, without a notion of type division (maybe using <a href="http://lambda-the-ultimate.org/node/2785" rel="nofollow">species</a>?), I don't see how to get from this form of AD to a power series. True enough. I just started down this path because I was thinking in terms of inductive families of types, and realized with open type functions that you could put a more interesting operation in than just a pair, etc.

And yeah, without a notion of type division (maybe using species?), I don’t see how to get from this form of AD to a power series.

]]>
By: apfelmus http://comonad.com/reader/2008/towards-formal-power-series-for-functors/comment-page-1/#comment-1275 apfelmus Tue, 13 May 2008 16:08:04 +0000 http://comonad.com/reader/2008/towards-formal-power-series-for-functors/#comment-1275 Yeah, just <code>instance Differentiable f => Differentiable (D f)</code> doesn't work. And concerning the power series, I think what you really want is <code>newtype Power f a = Power (f () :+: (a :*: Power (D f) a))</code> but that's wrong too, because you would have to divide by $latex \frac1{n!}$ somewhere. Power series are different from (but related to) automatic differentiation! Most likely, the impossible division can be included by using bags of n elements instead of powers <code>a :*: a :*: ...</code> (= ordered pairs) of n elements. In any case, the functor instance for power series is no problem, since a is used explicitly. Not sure in the case of automatic differentiation; the main problem here is indeed to somehow tell the compiler that <code>instance Functor f => Functor (D f)</code> But since type families are open, I guess that's not possible. I mean, a "mischievous" person could add a new case for this type family which violates this condition. So, the problem is not that the compiler doesn't grok it, the problem is that there is a good reason that the compiler doesn't accept it. Yeah, just
instance Differentiable f => Differentiable (D f)
doesn’t work.

And concerning the power series, I think what you really want is

newtype Power f a = Power (f () :+: (a :*: Power (D f) a))

but that’s wrong too, because you would have to divide by $latex \frac1{n!}$ somewhere. Power series are different from (but related to) automatic differentiation! Most likely, the impossible division can be included by using bags of n elements instead of powers a :*: a :*: ... (= ordered pairs) of n elements. In any case, the functor instance for power series is no problem, since a is used explicitly.

Not sure in the case of automatic differentiation; the main problem here is indeed to somehow tell the compiler that
instance Functor f => Functor (D f)
But since type families are open, I guess that’s not possible. I mean, a “mischievous” person could add a new case for this type family which violates this condition. So, the problem is not that the compiler doesn’t grok it, the problem is that there is a good reason that the compiler doesn’t accept it.

]]>