gpt4 book ai didi

haskell - 如何对 Haskell 中的类型执行分散/聚集操作?

转载 作者:行者123 更新时间:2023-12-02 12:09:23 24 4
gpt4 key购买 nike

我有一棵树,其中包含不同类型的节点。它们使用数据类型进行标记:

data Wrapping = A Int
| B String

我想写两个函数:

scatter :: Wrapping -> a
gather :: a -> Output

这个想法是我可以使用 (scatter.gather)::Wrapping -> Output。当然,分散和聚集函数都会有几种不同的变体(每个分散变体都有一个唯一的 Wrappingn 数据类型,但中间类型集始终是相同的),我希望能够干净地组合它们。

我遇到的问题是类型参数 a 并不是真正自由的,它是一个小的显式类型集(这里是 {Int,String})。如果我尝试将迄今为止的内容编码到 Haskell 类型类中,那么我会得到:

{-# LANGUAGE FlexibleInstances #-}
data Wrapping = A Int | B String

class Fanin a where
gather :: a -> String
instance Fanin Int where
gather x = show x
instance Fanin String where
gather x = x

class Fanout a where
scatter :: Fanout a => Wrapping -> a
instance Fanout Int where
scatter (A n) = n
instance Fanout String where
scatter (B x) = x

combined = gather.scatter

这两个类类型检查正常,但显然最后一行会抛出错误,因为 ghc 知道类型参数在每种情况下都匹配,仅在我定义的两个情况下匹配。我尝试过从一个类扩展另一个类的各种组合:

class Fanin a => Fanout a where ...
class Fanout a => Fanin a where ...

最后,我研究了 GADT 和存在类型来解决这个问题,但我在黑暗中跌跌撞撞。我找不到向 GHC 表达合法合格类型签名的方法,我尝试了以下组合:

{-# LANGUAGE RankNTypes #-}
class (forall a. Fanout a) => Fanin a where
class (forall a. Fanin a) => Fanout a where

问题:如何向 GHC 表达我想要将 a 限制为集合中的两种类型?

我感觉解决方案在于我研究过的一种技术,但我太迷失了,看不到它是什么......

最佳答案

The idea is that I can use (scatter.gather) :: Wrapping -> Output. There will of course be several different variations on both the scatter and the gather function (with each scatter variant having a unique Wrappingn datatype, but the set of intermediate types will always be the same) and I want to be able to cleanly compose them.

如果我理解正确的话,你想要不同的Wrapping类型但中间 a类型不断Either Int String 。我们可以在我们的类中反射(reflect)这些信息:

data Wrapping = A Int
| B String

class Fanout wrap where
scatter :: wrap -> Either Int String

instance Fanout Wrapping where
scatter (A n) = Left n
scatter (B str) = Right str

class Fanin output where
gather :: Either Int String -> output

instance Fanin String where
gather = either show id

combined :: Wrapping -> String
combined = gather . scatter

此外,从我从问题中收集到的信息来看,这个用例似乎不太适合输入类。特别是,我们可以去掉 Fanin ,然后 combined = either show id . scatter在我看来,比之前的定义更好。

仅当只有一个 Either Int String -> a 时,类型类解决方案才有意义。或a -> Either Int String函数对每个 a 都有意义,并且您想强制执行此操作。

关于haskell - 如何对 Haskell 中的类型执行分散/聚集操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32473227/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com