首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >haskell中最不固定型后的双函子

haskell中最不固定型后的双函子
EN

Stack Overflow用户
提问于 2016-01-14 22:22:10
回答 2查看 153关注 0票数 5

我不知道如何在不动点之后导出函式实例:

代码语言:javascript
复制
data FreeF f a next  = PureF a | FreeF (f next)  deriving (Functor)

data Mu f  = In { out :: f ( Mu f ) }

newtype Free f a = Free(  Mu (FreeF f a)  )

instance Functor f => Functor (Free f) where
     fmap h (Free (out -> PureF a))  = Free (In (PureF (h a)))
     fmap h (Free (out -> FreeF fn)) = Free (In (fmap undefined undefined)) --stuck

如果我修改Mu以接受一个额外的类型参数,我可以一直进行到.:

代码语言:javascript
复制
data Mu f a  = In { out :: f ( Mu f a )  } deriving (Functor)

newtype Free f a = Free(  Mu (FreeF f a) a )

instance Functor f => Functor (Free f ) where
     fmap h (Free (out -> PureF a))  = Free . In . PureF $ h a
     fmap h (Free (out -> FreeF fn)) = Free . In . FreeF $ fmap undefined fn 

这里我需要undefined :: Mu (FreeF f a) a -> Mu (FreeF f b) b,但是mu f是同一个f的函子,在这里它的类型是不同的。

解决这个问题的正确方法是什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-01-14 23:43:54

mu f是同一个f的函子,在这里它的类型是不同的。

幸运的是,我们正在定义Functor (Free f),我们实际上使用这个Functor实例来映射PureF构造函数中的aFunctor (Free f)抽象了a的所有“内部”事件。

因此,每当我们想要映射两次a时(例如,当我们想实现FreeF f a (Mu (FreeF f a)) -> FreeF f b (Mu (FreeF f b))时),我们都可以通过将所有东西打包回Free,映射,然后再展开。

以下是使用原始数据定义进行的检查:

代码语言:javascript
复制
newtype Free f a = Free {unFree :: Mu (FreeF f a)} -- add "unFree"

instance Functor f => Functor (Free f) where
     fmap h (Free (In (PureF a)))  = Free (In (PureF (h a)))
     fmap h (Free (In (FreeF fn))) =
       Free (In (FreeF (fmap (unFree . fmap h . Free) fn)))

一些测试:

代码语言:javascript
复制
{-# LANGUAGE UndecidableInstances, StandaloneDeriving #-}

deriving instance Show (f (Mu f)) => Show (Mu f)
deriving instance Show (Mu (FreeF f a)) => Show (Free f a)       

foo :: Free [] Int
foo = Free $ In $ FreeF [ In $ PureF 100, In $ PureF 200 ]

> fmap (+100) foo
Free {unFree = In {out = FreeF [In {out = PureF 200},In {out = PureF 300}]}}
票数 4
EN

Stack Overflow用户

发布于 2016-01-14 23:21:04

我以前没做过这件事,但我想我看到了些什么。关于向Mu添加参数的直觉是很好的,但是您需要将它传递给Free f,也就是说,f采用两个参数而不是一个参数:

代码语言:javascript
复制
newtype Mu f a = In { out :: f (Mu f a) a }

Mu f应该是一个在适当条件下的Functor,这将为您提供您要寻找的实例。这些条件是什么?我们需要:

代码语言:javascript
复制
fmap' :: (a -> b) -> f (Mu f a) a -> f (Mu f b) b

我们期望f在其第二个参数中是函数式,所以这是没有问题的。所以我们真正需要的是

代码语言:javascript
复制
f (Mu f a) b -> f (Mu f b) b
           ^               ^
           +--not varying--+

我们可以递归地使用实例来获取Mu f a -> Mu f b,因此看起来我们只需要f在其第一个参数中也是一个函子。因此:

代码语言:javascript
复制
class Bifunctor f where
    bimap :: (a -> c) -> (b -> d) -> f a b -> f c d

那么,您应该能够编写合适的实例。

代码语言:javascript
复制
instance (Functor f) => Bifunctor (FreeF f) ...
instance (Bifunctor f) => Functor (Mu f) ...
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34800925

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档