这个特殊的仿函数结构叫什么?

时间:2013-04-20 18:10:50

标签: haskell category-theory applicative

假设F是一个带有附加定律的应用函子(使用Haskell语法):

  1. pure (const ()) <*> m === pure ()
  2. pure (\a b -> (a, b)) <*> m <*> n === pure (\a b -> (b, a)) <*> n <*> m
  3. pure (\a b -> (a, b)) <*> m <*> m === pure (\a -> (a, a)) <*> m
  4. 如果我们省略(3。),那么调用的结构是什么?

    我在哪里可以找到有关这些法律/结构的更多信息?

    对评论的评论

    满足(2.)的函数通常称为交换。

    现在的问题是,(1.)是否暗示(2.)以及如何描述这些结构。 我对满足(1-2。)而不是(3。)

    的结构特别感兴趣

    示例:

    • 读者monad满足(1-3。)
    • 交换幺半群上的作家monad只满足(2。)
    • 下面给出的monad F满足(1-2。)但不满足(3。)

    F的定义:

    {-# LANGUAGE GeneralizedNewtypeDeriving #-}
    {-# LANGUAGE RankNTypes #-}
    import Control.Monad.State
    
    newtype X i = X Integer deriving (Eq)
    
    newtype F i a = F (State Integer a) deriving (Monad)
    
    new :: F i (X i)
    new = F $ modify (+1) >> gets X
    
    evalF :: (forall i . F i a) -> a
    evalF (F m) = evalState m 0
    

    我们仅导出XFnewevalF和实例类型。

    检查以下内容:

    • liftM (const ()) m === return ()
    • liftM2 (\a b -> (a, b)) m n === liftM2 (\a b -> (b, a)) n m

    另一方面,liftM2 (,) new new无法取代liftM (\a -> (a,a)) new

    test = evalF (liftM (uncurry (==)) $ liftM2 (,) new new)
        /= evalF (liftM (uncurry (==)) $ liftM (\a -> (a,a)) new)
    

    评论C. A. McCann的回答

    我有一个证明草图(1.)暗示(2。)

    pure (,) <*> m <*> n
    

    =

    pure (const id) <*> pure () <*> (pure (,) <*> m <*> n)
    

    =

    pure (const id) <*> (pure (const ()) <*> n) <*> (pure (,) <*> m <*> n)
    

    =

    pure (.) <*> pure (const id) <*> pure (const ()) <*> n <*> (pure (,) <*> m <*> n)
    

    =

    pure const <*> n <*> (pure (,) <*> m <*> n)
    

    = ... =

    pure (\_ a b -> (a, b)) <*> n <*> m <*> n
    

    =见下面=

    pure (\b a _ -> (a, b)) <*> n <*> m <*> n
    

    = ... =

    pure (\b a -> (a, b)) <*> n <*> m
    

    =

    pure (flip (,)) <*> n <*> m
    

    观察

    缺少的部分首先考虑

    pure (\_ _ b -> b) <*> n <*> m <*> n
    

    = ... =

    pure (\_ b -> b) <*> n <*> n
    

    = ... =

    pure (\b -> b) <*> n
    

    = ... =

    pure (\b _ -> b) <*> n <*> n
    

    = ... =

    pure (\b _ _ -> b) <*> n <*> m <*> n
    

    引理

    我们使用以下引理:

    pure f1 <*> m  ===   pure g1 <*> m
    pure f2 <*> m  ===   pure g2 <*> m
    

    意味着

    pure (\x -> (f1 x, f2 x)) m  ===  pure (\x -> (g1 x, g2 x)) m
    

    我只能间接地证明这个引理。

    缺少部分

    有了这个引理和我们可以证明的第一个观察

    pure (\_ a b -> (a, b)) <*> n <*> m <*> n
    

    =

    pure (\b a _ -> (a, b)) <*> n <*> m <*> n
    

    这是缺失的部分。

    问题

    这是否已在某处证实(可能是一般化的形式)?

    说明

    (1。)暗示(2.)但是否则(1-3。)是独立的。

    为了证明这一点,我们还需要两个例子:

    • 下面给出的monad G满足(3.)但不满足(1-2。)
    • 下面给出的monad G'满足(2-3。)但不满足(1。)

    G的定义:

    newtype G a = G (State Bool a) deriving (Monad)
    
    putTrue :: G ()
    putTrue = G $ put True
    
    getBool :: G Bool
    getBool = G get
    
    evalG :: G a -> a
    evalG (G m) = evalState m False
    

    我们只导出类型GputTruegetBoolevalGMonad个实例。

    G'的定义与G的定义类似,但有以下不同之处:

    我们定义并导出execG

    execG :: G' a -> Bool
    execG (G m) = execState m False
    

    我们不导出 getBool

1 个答案:

答案 0 :(得分:20)

您的第一部法律是一项非常强烈的要求;这意味着仿函数不具有独立于参数部分的独特“形状”。这排除了包含额外值(StateWriter和&.c。)的任何仿函数以及使用和类型的任何仿函数(Either[]和&amp; C。)。因此,这限制了我们使用固定大小的容器。

你的第二定律要求交换性,这意味着嵌套的顺序(即函子组成)并不重要。这可能实际上是由第一定律暗示的,因为我们已经知道仿函数不能包含除参数值之外的任何信息,并且您明确要求在此保留它。

你的第三定律要求算子也是幂等的,这意味着使用fmap在其内部嵌套某些东西就等同于它自己。这可能意味着如果仿函数也是一个monad,join涉及某种“对角线”。基本上,这意味着liftA2 (,)应该表现得像zip,而不是笛卡尔积。

第二个和第三个一起暗示无论仿函数可能具有多少“原语”,任何组合等同于以任何顺序组合每个原语中的至多一个。第一个暗示如果你抛弃参数信息,任何基元组合都与使用none完全相同。

总之,我认为你拥有的是the class of functors isomorphic to Reader。也就是说,f a描述由其他类型索引的类型a的值的仿函数,例如自然数的子集(对于固定大小的容器)或任意类型(与{{1一样) }})。

不幸的是,我不确定如何令人信服地证明上述大部分内容。