繁体   English   中英

Haskell-具有函数构造函数的数据类型上的自定义仿函数实例

[英]Haskell - Custom functor instance on data type with function constructor

我无法为自定义数据类型编写自己的functor实例(无法更改)。 数据类型定义为:

data Foo a = Baz String (Qux -> Foo a) | Bar a
data Qux = None | Quux String

我的问题是为Foo类型写一个仿函数。 具体来说,我不确定如何将我的函子函数f正确地应用于Foo的函数。 我正在考虑以某种方式在构造函数中调用该函数,但是由于我没有任何可用的Qux ,因此我陷入了困境。

instance Functor Foo where
    fmap f (Bar a) = Bar (f a)
    fmap f (Baz s ???) = Baz s (???) -- What goes here?

    -- Clearly, something like this doesn't work
    -- fmap f (Baz s g) = Baz s (f g) 

    -- I've also tried something like this, but I'm not sure where to go from there
    -- fmap f (Baz s (None   -> Bar b)) = Baz s (f b) ???
    -- fmap f (Baz s (Quux x -> Bar b)) = Baz s ???

让我们从完成此等式的左侧开始。 我们可以编写g将您的函数绑定到变量。

fmap f (Baz sg) = Baz s (???)

然后,我们需要用另一个函数填充问号,该函数采用Qux并返回Foo b

fmap f (Baz sg) = Baz s (\\q -> ???)

我们只能用q做一件事情,那就是将g应用于它。

fmap f (Baz sg) = Baz s (\\q -> gq)

但是,这给了我们Foo a ,但是我们需要Foo b 我们没有执行此操作的功能。 但是,我们确实有f ,它取a并返回b 如果只有一种方法可以将fmap a -> b转换为Foo a -> Foo b fmap Foo a -> Foo b ...哦,等等,这就是fmap

fmap f (Baz sg) = Baz s (\\q -> fmap f (gq))

如果要以无点符号( https://wiki.haskell.org/Pointfree )编写函数,则可以执行此操作。

fmap f (Baz sg) = Baz s (fmap f . g)

遵循以下类型:

fmap f (Baz s g) = GOAL
   -- f    :: a -> b
   -- s    :: String
   -- g    :: Qux -> Foo a
   -- GOAL :: Foo b

因此,我们正在寻找Foo b (目标行)。 我们可以用BarBaz制作一个。 fmap应该保留结构,因此应该是Baz BazString参数可能不应更改,这只是引起问题的第二个参数。

fmap f (Baz s g) = Baz s GOAL
   -- f    :: a -> b
   -- s    :: String
   -- g    :: Qux -> Foo a
   -- GOAL :: Qux -> Foo b

现在我们必须做一个Qux -> Foo b 如果需要执行功能,lambda是必不可少的工具(有其他工具,但是lambda是祖父)。 所以做一个lambda:

fmap f (Baz s g) = Baz s (\x -> GOAL)
   -- f    :: a -> b
   -- s    :: String
   -- g    :: Qux -> Foo a
   -- x    :: Qux          <-- NEW
   -- GOAL :: Foo b

注意,我们现在有一个x :: Qux可以使用。 使用gx可以创建Foo a ,然后递归使用fmap f 1可以生成所需的Foo b

请注意,我是如何一次仅一步一步地填写表达式,用目标替换未知参数,然后退后一步来考虑范围内的变量以及它们的类型。 继续执行此操作,直到明确目标的路径。


1递归类型通常将具有相应的递归fmap定义。 递归在fmap发生的fmap与类型递归的方式完全对应。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM