Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 如何在ADT';s构造函数';谁的论点?_Haskell - Fatal编程技术网

Haskell 如何在ADT';s构造函数';谁的论点?

Haskell 如何在ADT';s构造函数';谁的论点?,haskell,Haskell,我有一个数据类型(如下GADT格式所示): 我想做的是,能够将一些函数monoidm=>testa->m一般地应用于构造函数中testa的任何给定实例,然后mappend全部应用 例如,给定f: f :: Test a -> [Int] f (C1 n _) = [n] f _ = [] 我想要一个函数g,它可以映射每个构造函数参数,如下所示: g :: Monoid m => (Test a -> m) -> Test a -> m g f v@(

我有一个数据类型(如下GADT格式所示):

我想做的是,能够将一些函数
monoidm=>testa->m
一般地应用于构造函数中
testa
的任何给定实例,然后
mappend
全部应用

例如,给定f:

f :: Test a -> [Int]
f (C1 n _) = [n]
f _        = []
我想要一个函数g,它可以映射每个构造函数参数,如下所示:

g :: Monoid m => (Test a -> m) -> Test a -> m
g f v@(C1 Int _) = f v
g f (C2 x y _)   = f x `mappend` f y
g f (C3 x _)     = f x
...
除了我不想写
g
,我想写一个
g
的泛型版本,它可以对任何支持的数据类型执行此操作(我认为GHC.Generics可能很适合此操作,但无法正确获取类型)。 i、 e.我想将遍历我的数据结构的实际机制(使用基于
mappend
的折叠重复应用
f
)与感兴趣的位(上面
g
中的
C1
的终端情况)分开


有什么想法吗?

实际上,我会更深入地研究GHC.Generics,如果你没有的话,一定会阅读

我将在这里概述另一种方法,即使用不动点类型,它非常适合这个问题

newtype Mu f = Roll { unroll :: f (Mu f) }

-- Replace all recursive constructors with r.
-- If any of them are nonregular (e.g. C3 :: Test Int -> Test a)
-- then this approach gets quite a bit more complicated, so I hope not.
data TestF a r where
  C1 :: Int -> a -> TestF a r
  C2 :: r -> r -> a -> TestF a r
  ...

-- This will take care of finding the recursive constructors
deriving instance Foldable (TestF a) 

-- This is your actual type (might want to wrap it in a newtype)
type Test a = Mu (TestF a)

foldMapRec :: (Foldable f, Monoid m) => (Mu f -> m) -> Mu f -> m
foldMapRec f (Roll a) = foldMap f a

实际上,我并没有从固定点类型中得到太多的使用,它们似乎总是比它们的价值更麻烦。但是现在实现了
模式同义词
,我认为这会更好一些。无论如何,我只是想向您展示这一点供您考虑。

看起来您想要做的或多或少就是本文(第3节)中所述的函数
组合的功能

该包裹声称有一个


对应于您似乎正在寻找的操作。

是否应该仅将
f
应用于使用
C1
构造函数生成的值?为什么不是
C2
C3
构造函数?它只适用于没有递归参数的构造函数吗?如果有一个
C4 Int(testa)
构造函数或
C5 Int
构造函数,会发生什么?不,
f
可以选择它想要的
测试a
部分,因此根据问题中给出的
f
的定义,我希望
g
C4 I r
返回
fr
(或记忆)对于
C5 i
。希望这能澄清问题。你的评论实际上让我意识到
f
调用函数进行折叠可能比使用
g
调用
f
更容易。GHC。泛型是一个很好的选择,如果你以前从未使用过它,它可能很难使用。你读过吗?--当我读这篇文章的时候不再是一个黑暗的咒语,开始成为一个有用的工具,想象一下!
newtype Mu f = Roll { unroll :: f (Mu f) }

-- Replace all recursive constructors with r.
-- If any of them are nonregular (e.g. C3 :: Test Int -> Test a)
-- then this approach gets quite a bit more complicated, so I hope not.
data TestF a r where
  C1 :: Int -> a -> TestF a r
  C2 :: r -> r -> a -> TestF a r
  ...

-- This will take care of finding the recursive constructors
deriving instance Foldable (TestF a) 

-- This is your actual type (might want to wrap it in a newtype)
type Test a = Mu (TestF a)

foldMapRec :: (Foldable f, Monoid m) => (Mu f -> m) -> Mu f -> m
foldMapRec f (Roll a) = foldMap f a
composOpMonoid :: (Uniplate a, Monoid m) => (a -> m) -> a -> m