【问题标题】:How to write fmap for a Functor that has a function in it's data type definition?如何为在其数据类型定义中具有函数的 Functor 编写 fmap?
【发布时间】:2019-03-24 15:27:36
【问题描述】:

我的数据定义如下:

data FGM a = Pure a | GMAction Integer Integer (PlayerMsg -> FGM a)
data PlayerMsg = Guess Integer | Surrender
    deriving (Eq, Show)

FGM代表猜数游戏,2个整数是上下界,a是最后要返回的值,playermsg是玩家的猜测。 我想让 FGM 成为 Functor,所以我试图为它定义一个 fmap。问题是我不知道如何处理 FGM 的(PlayerMsg -> FGM a) 部分。

根据我对给出的测试用例的理解,对于fmap g (someFGM),g 应该只应用于Pure,如果是GMAction,fmap 应该使用PlayerMsg 并生成下一个 FGM,直到它达到Pure.

这是我尝试过的:

instance Functor FGM where
    fmap g (Pure a) = Pure (g a)
    fmap g (GMAction upper lower thing) = GMAction upper lower (fmap g (\x -> case (thing x) of 
                                                                                Pure a -> Pure a
                                                                                GMAction u l t -> GMAction u l t))

但是当我尝试对此进行测试时,我得到了这个错误:

Occurs check: cannot construct the infinite type:
  b ~ FGM b
Expected type: PlayerMsg -> FGM b
  Actual type: PlayerMsg -> b
In the third argument of 'GMAction', namely '(fmap g (\x -> case (thing x) of 
                                                                                Pure a -> Pure a
                                                                                GMAction u l t -> GMAction u l t))'
In the expression:...

我也试过

fmap g (GMAction upper lower thing) = GMAction upper lower (fmap g thing)

得到了同样的错误。

我试图搜索具有像PlayerMsg -> FGM a 这样的参数的数据的示例,但找不到任何东西。 this 有点相似,但对我不起作用(这是我第一个失败的例子)。有人可以帮我定义这个 fmap 或告诉我在哪里了解这个吗?

【问题讨论】:

  • 旁注:带有case表达式的lambda等于thing。

标签: haskell


【解决方案1】:

试试fmap g (GMAction upper lower thing) = GMAction upper lower ((fmap g) . thing)。注意函数组成;这是必要的,因为您需要在函数的 result 上 fmap。

【讨论】:

  • 是的,它成功了!谢谢!是的,这是错字,我会编辑它
【解决方案2】:

GHC 内置的推导Functor 的规则足以处理这种简单的情况。

{-# LANGUAGE DeriveFunctor #-}
data FGM a = Pure a | GMAction Integer Integer (PlayerMsg -> FGM a) deriving Functor
data PlayerMsg = Guess Integer | Surrender
    deriving (Eq, Show)

【讨论】:

  • 真的 - 尽管我在上面回答 - 这也是我通常使用的。很高兴让计算机为您编写代码!
  • @CeilviaC:您还可以看到 GHC 从带有-ddump-deriv 标志的deriving 子句生成的代码。 (如果您使用的是 Stack,这将在您的 .stack-work 目录中生成一个 .dump-deriv 文件。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-25
  • 1970-01-01
  • 2016-10-04
相关资源
最近更新 更多