【问题标题】:deriving a Functor for an infinite Stream为无限流派生函子
【发布时间】:2023-03-14 15:23:01
【问题描述】:

我正在关注这个blog 关于 F 代数 它解释了

终端代数通常在编程中被解释为配方 用于生成(可能是无限的)数据结构或转换 系统。

然后说

余代数的一个典型例子是基于一个函子,其固定 点是类型 e 元素的无限流。这是 函子:

data StreamF e a = StreamF e a
  deriving Functor

这是它的固定点:

data Stream e = Stream e (Stream e)

我试过代码here

相关部分是

newtype Fix f = Fix (f (Fix f))
unFix :: Fix f -> f (Fix f)
unFix (Fix x) = x

cata :: Functor f => (f a -> a) -> Fix f -> a
cata alg = alg . fmap (cata alg) . unFix

ana :: Functor f => (a -> f a) -> a -> Fix f
ana coalg = Fix . fmap (ana coalg) . coalg

data StreamF e a = StreamF e a
    deriving Functor
data Stream e = Stream e (Stream e)

era :: [Int] -> StreamF Int [Int]
era (p : ns) = StreamF p (filter (notdiv p) ns)
    where notdiv p n = n `mod` p /= 0

primes = ana era [2..]

我收到了这个错误

main.hs:42:14: error:
• Can’t make a derived instance of ‘Functor (StreamF e)’:
You need DeriveFunctor to derive an instance for this class
• In the data declaration for ‘StreamF’

我哪里错了?

【问题讨论】:

  • 你不能在 vanilla Haskell 中使用deriving (Functor)。您需要文件顶部的编译指示{-# LANGUAGE DeriveFunctor #-}。更多信息here.

标签: haskell functor recursive-datastructures


【解决方案1】:

deriving 在没有使用语言扩展的情况下在 Haskell 中非常有限。由于编译器不能总是计算出Functor 实例应该是什么,deriving Functor 不是标准的 Haskell。

但是,有一个语言扩展允许这样做,即-XDeriveFunctor。要启用此扩展,请执行以下操作之一:

  • 使用标志 -XDeriveFunctor 编译。 (例如:编译时运行ghc -XDeriveFunctor Main.hs

  • 在文件顶部写入编译指示{-# LANGUAGE DeriveFunctor #-}

添加此编译指示后文件的外观如下:

{-# LANGUAGE DeriveFunctor #-}

newtype Fix f = Fix (f (Fix f))
unFix :: Fix f -> f (Fix f)
unFix (Fix x) = x

cata :: Functor f => (f a -> a) -> Fix f -> a
cata alg = alg . fmap (cata alg) . unFix

ana :: Functor f => (a -> f a) -> a -> Fix f
ana coalg = Fix . fmap (ana coalg) . coalg

data StreamF e a = StreamF e a
    deriving Functor
data Stream e = Stream e (Stream e)

era :: [Int] -> StreamF Int [Int]
era (p : ns) = StreamF p (filter (notdiv p) ns)
    where notdiv p n = n `mod` p /= 0

primes = ana era [2..]

如果您打算使用 GHCi,请在加载文件之前使用:set -XDeriveFunctor

【讨论】:

  • 相反,编译器可以派生一个Functor 实例(这样做相当简单),它只是不是必需所以在 Haskell 2010 中。
猜你喜欢
  • 1970-01-01
  • 2019-06-11
  • 2021-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-18
  • 2017-01-19
相关资源
最近更新 更多