Haskell Lax幺半函子的消歧
我试图构造一个lax幺半函子(Haskell的Haskell Lax幺半函子的消歧,haskell,typeclass,category-theory,Haskell,Typeclass,Category Theory,我试图构造一个lax幺半函子(Haskell的实用的),它尽可能符合范畴理论。主要是作为练习分类思维的练习。我已经上了几节课,我很高兴能为这节课做准备,现在我必须自己上这节课。我把所有这些积木都放在柱子下面,以供参考 这就是我的过程: 首先,显然有一个函子 class ( Functor cat1 cat2 f ) => MonoidalFunctor cat1 cat2 f 函子位于两个幺半类之间,所以我们也添加了它们 class ( Functor cat1 ca
实用的
),它尽可能符合范畴理论。主要是作为练习分类思维的练习。我已经上了几节课,我很高兴能为这节课做准备,现在我必须自己上这节课。我把所有这些积木都放在柱子下面,以供参考
这就是我的过程:
首先,显然有一个函子
class
( Functor cat1 cat2 f
)
=> MonoidalFunctor cat1 cat2 f
函子位于两个幺半类之间,所以我们也添加了它们
class
( Functor cat1 cat2 f
, MonoidalCategory cat1 bf1 i1
, MonoidalCategory cat2 bf2 i2
)
=> MonoidalFunctor cat1 cat2 bf1 bf2 i1 i2 f
现在由于i1
和i2
分别由cat1
和bf1
和cat2
和bf2
确定,我们可以添加一个fundep
class
( Functor cat1 cat2 f
, MonoidalCategory cat1 bf1 i1
, MonoidalCategory cat2 bf2 i2
)
=> MonoidalFunctor cat1 cat2 bf1 bf2 i1 i2 f
| cat1 bf1 -> i1
, cat2 bf2 -> i2
现在要完成这个类,我们需要添加两个自然转换,相当于haskell函数fzip
和pure
,因此我们将它们称为
class
( Functor cat1 cat2 f
, MonoidalCategory cat1 bf1 i1
, MonoidalCategory cat2 bf2 i2
)
=> MonoidalFunctor cat1 cat2 bf1 bf2 i1 i2 f
| cat1 bf1 -> i1
, cat2 bf2 -> i2
where
fzip :: (f x `bf2` f y) `cat2` f (x `bf1` y)
pure :: i2 `cat2` f i1
在我们编译这个之前,我已经看到了一个问题。我们在这两个函数中的任何地方都没有提到cat1
!我无法从类中其他类型的任何组合中导出cat1。这意味着哈斯克尔对fzip
和pure
不明确。现在我们似乎无法从我们已经拥有的任何东西中推断出cat1,也就是说它不应该有一个fundep。虽然一个基金会可以解决这个问题,但从数学角度来看,它是不合理的
现在我可以使用代理来解决这个问题。但我认为没有他们也有可能逃脱fzip
和pure
不是Haskell应用程序的定义方式,即使它们是最小的。我想知道一个liftA2
或()
的类比,是否可以提到所有需要的类型,以使这一点明确无误
在不牺牲理论的情况下,是否有一种重组方法使这个类变得明确?
资源:
import Data.Kind
( Type
)
class Category cat where
id :: cat a a
(.) :: cat b c -> cat a b -> cat a c
-- | Isomorphism are morphisms with an inverse.
-- It is expected that for any @i :: Iso cat a b@:
--
-- prop> (fwd iso) . (bwd iso) = id
-- prop> (bwd iso) . (fwd iso) = id
--
-- That is to say `Iso`s should be isomorphisms.
data Iso cat a b = Iso
{ fwd :: cat a b
, bwd :: cat b a
}
instance
( Category cat
)
=> Category (Iso cat)
where
id = Iso id id
f . g = Iso (fwd f . fwd g) (bwd g . bwd f)
class
( Category s
, Category t
)
=> Functor (s :: a -> a -> Type) (t :: b -> b -> Type) (f :: a -> b)
where
map :: s x y -> t (f x) (f y)
class
( Category cat1
, Category cat2
, Category cat3
)
=> Bifunctor
(cat1 :: a -> a -> Type)
(cat2 :: b -> b -> Type)
(cat3 :: c -> c -> Type)
(p :: a -> b -> c)
where
bimap :: cat1 x y -> cat2 z w -> cat3 (p x z) (p y w)
class
( Bifunctor cat cat cat p
)
=> MonoidalCategory
(cat :: a -> a -> Type)
(p :: a -> a -> a)
(i :: a)
| cat p -> i
where
associator :: Iso cat (x `p` (y `p` z)) ((x `p` y) `p` z)
leftUnitor :: Iso cat (i `p` x) x
rightUnitor :: Iso cat (x `p` i) x
cat1被“提到”为
f
的领域,所有希望都没有丧失。我想你需要f->cat1
fundep,至少,可能需要更多。考虑关联类型。@ LuQUI也被称为类别,其中<代码> BF1 < /代码>是单性的。但遗憾的是,这两个函数都不能唯一地确定cat1。你想要一个同时具有多个源类别的函子吗?我想你可能需要降低你的标准一点,如果你想把这件事说清楚的话。CT中没有任何东西需要这样一个函子,afaik。(当然,它们有时是“双关语”,但您始终可以将其转换为函子具有唯一源和目标类别的版本)确定。另一个选择是设置AllowAmbiguousTypes
和TypeApplications
,然后您可以对事物进行完全通用的建模(这让人懂得欣赏hindley milner的推理平衡)。是的,据我所知,这很不方便,但在形式上并不不可靠。我从来没有在哈斯凯尔找到一种几乎方便的CT常规治疗方法——“它可以编译!”通常是一个巨大的胜利。不管怎么说,你的问题是关于不牺牲理论,但现在我们得到了真相:你希望它是美丽的。这是一个风格问题,有很大的审美空间需要探索。无论如何,根据你所说的,我建议使用AllowAmbiguousTypes
/TypeApplications
cat1被“提到”为f
的领域,所有希望都不会失去。我想你需要f->cat1
fundep,至少,可能需要更多。考虑关联类型。@ LuQUI也被称为类别,其中<代码> BF1 < /代码>是单性的。但遗憾的是,这两个函数都不能唯一地确定cat1。你想要一个同时具有多个源类别的函子吗?我想你可能需要降低你的标准一点,如果你想把这件事说清楚的话。CT中没有任何东西需要这样一个函子,afaik。(当然,它们有时是“双关语”,但您始终可以将其转换为函子具有唯一源和目标类别的版本)确定。另一个选择是设置AllowAmbiguousTypes
和TypeApplications
,然后您可以对事物进行完全通用的建模(这让人懂得欣赏hindley milner的推理平衡)。是的,据我所知,这很不方便,但在形式上并不不可靠。我从来没有在哈斯凯尔找到一种几乎方便的CT常规治疗方法——“它可以编译!”通常是一个巨大的胜利。不管怎么说,你的问题是关于不牺牲理论,但现在我们得到了真相:你希望它是美丽的。这是一个风格问题,有很大的审美空间需要探索。不管怎样,根据你说的,我建议使用AllowAmbiguousTypes
/TypeApplications