haskell - 具有类型约束的 GADT 的仿函数实例

标签 haskell functor type-constraints

今天我想研究是否有可能以这种方式构造一个数据类型,它不存储其类型签名的类型的数据,而是存储它的另一种表示。所以,这是我尝试使用类型构造函数为 a 的 GADT。 , 但类型为 ByteString 的数据构造函数.

{-# LANGUAGE GADTs #-}
import Data.ByteString.Char8
import Data.Serialize

data Serialized a where
    MkSerialized :: (Serialize a) => ByteString -> Serialized a

现在我可以定义一个 decode'通过以下方式发挥作用:
decode' :: (Serialize a) => Serialized a -> a
decode' (MkSerialized bs) = let Right r = (decode bs) in r

它有效:
let s = MkSerialized (encode "test") :: Serialized String
print $ decode' s     -- prints "test"

我现在的问题是我想要 Serialized成为 Functor 的一个实例.
instance Functor Serialized where
    fmap f (MkSerialized bs) = MkSerialized (encode (f (right (decode bs))))
                               where right (Right r) = r

但是我得到错误(Serialize b)无法推断。如何约束 Functor 实例,以便 Serializefmap 中强制执行?

最佳答案

您可以使用 CoYoneda 仿函数来做到这一点。

这个想法很简单:有一个额外的功能领域,你可以在其中积累 fmap荷兰国际集团的功能。当您解码您的值时,然后应用该功能。

这是代码:

{-# LANGUAGE GADTs #-}
import Data.ByteString.Char8
import Data.Serialize

data Serialized a where
    MkSerialized
      :: (Serialize a)
      => ByteString -> (a -> b) -> Serialized b

decode' :: Serialized a -> a
decode' (MkSerialized bs f) = let Right r = decode bs in f r

instance Functor Serialized where
    fmap f (MkSerialized bs g) = MkSerialized bs (f . g)

这也有自动融合多个 fmap 的好处。 s 而不是重复的解码和编码,就像你的情况一样。

关于haskell - 具有类型约束的 GADT 的仿函数实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17157579/

相关文章:

haskell - 如何将归纳推理应用于 `GHC.TypeLits.Nat` ?

haskell - 不变仿函数的例子?

c++ - 通过引用将对象参数传递给仿函数

c++ - 如何在 C++ 中为多个类实现公共(public)仿函数

swift - 如何为可添加参数创建通用函数?

c# - 用作类型参数约束的空接口(interface)或空基类

c# - 通用 with where 子句需要显式转换

使用 Maybe 的 Haskell 代码 zipWith

haskell - 尝试对其键的子集进行镜头/遍历图多重更新

haskell - 处理 Haskell 函数中的错误