haskell中类型的等价表示(2)–Sum

前面给了一个Product的等价表示,还有一种是Sum的。

同样的先给出两种表示。

表示:

data S a b =  L a | R b

等价的表示:

newtype S' a b = S' { unS' :: forall r. (a -> r) -> (b -> r) -> r }

证明:

这里对于S’,forall r限制了可能的值。由于r不可知,所有只能是下面的两种形式:

sl = \f g -> f x

sr = \f g -> g y

可以证明:

sl id g' == id x == x

sr f' id == id y == y

这里g’和f’未知,但是我们可以用不定点来替代。

g' = \_ -> fix id
 
f’ = \_ ->fix id

所以递归的表示为:

sl = \f g -> f (sl id (\_ -> fix id))

sr = \f g -> g (sr (\_ ->fix id) id)

剩下的给出一一映射关系:

toS' :: S a b -> S' a b
toS' (L a) = S' (\f g -> f a)
toS' (R b) = S' (\f g -> g b)

反方向比较麻烦一点,我们需要判断是S'两种形式的哪一种。

我们给出一个helper函数toTrue和toFalse,用它们来test我们的S'表示,由此来判断是哪种。

toTrue :: a -> Bool
toTrue _ = True

toFalse :: a -> Bool
toFalse _ = False
fromS' :: S' a b -> S a b
fromS' (S' s) = case (s toTrue toTrue) == (s toFalse toTrue) of
                        True -> R (s (\_ ->fix id) id)
                        False -> L (s id (\_ ->fix id))

好了,剩下的不证明了。 :)

结论:

有了RankNTypes,代数数据结构不是必须的。(结论太早?没有考虑递归的代数数据结构:))

后面会谈谈free monad的非代数数据结构表示,因为Free monad可以看成是很多层的数据包装,所以等价的函数表示会跟高效。

posted @ 2015-03-23 23:45  wehu  阅读(1133)  评论(0编辑  收藏  举报