为无限流派生一个Functor

问题描述 投票:1回答:1

我正在关注这个关于F-algebras的blog它解释了这一点

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

并说

代数的规范示例基于仿函数,其固定点是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’

我哪里错了?

haskell functor
1个回答
1
投票

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

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

  • 用旗帜-XDeriveFunctor编译。 (例如:编译时运行ghc -XDeriveFunctor Main.hs
  • 将pragma {-# LANGUAGE DeriveFunctor #-}写在文件的顶部。

以下是添加此pragma后文件的外观:

{-# 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

© www.soinside.com 2019 - 2024. All rights reserved.