Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.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 具有类型约束的GADT的函子实例_Haskell_Functor_Type Constraints - Fatal编程技术网

Haskell 具有类型约束的GADT的函子实例

Haskell 具有类型约束的GADT的函子实例,haskell,functor,type-constraints,Haskell,Functor,Type Constraints,今天,我想研究是否有可能以这样的方式构造一个数据类型,即它不存储其类型签名类型的数据,而是存储它的另一种表示形式。因此,这里是我对GADT的尝试,它有一个类型为a的类型构造函数,但有一个类型为ByteString的数据构造函数 {-# LANGUAGE GADTs #-} import Data.ByteString.Char8 import Data.Serialize data Serialized a where MkSerialized :: (Serialize a) =&g

今天,我想研究是否有可能以这样的方式构造一个数据类型,即它不存储其类型签名类型的数据,而是存储它的另一种表示形式。因此,这里是我对GADT的尝试,它有一个类型为
a
的类型构造函数,但有一个类型为
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"
我现在的问题是,我希望
序列化
成为
Functor
的一个实例

instance Functor Serialized where
    fmap f (MkSerialized bs) = MkSerialized (encode (f (right (decode bs))))
                               where right (Right r) = r
但我得到的错误(序列化b)无法推断。如何约束函子实例,以便在
fmap
中强制执行
Serialize

您可以使用CoYoneda函子执行此操作

想法很简单:有一个额外的函数字段,在这里你可以累积你的
fmap
ing函数。当你解码你的值,然后应用该函数

代码如下:

{-# 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的优点,而不是像您的情况那样重复进行解码和编码。

您不能<代码>函子不允许要求对类型参数进行约束。在
rmonad
包中有一个受限函子类。也许你可以使用它。这与你的问题无关——这在
Functor
中确实是不可能的——但我觉得有义务提及:默认情况下,请不要使用
Data.ByteString.Char8
!它是一个坏模块,鼓励坏代码。它有时也有一些用途,但您的代码与
数据同样有效。ByteString
,这不会引起对Unicode的误解。为了它的价值,您可以创建
CoYoneda
样式的数据类型,如
数据序列化a,其中MkSerialized::Serialize x=>ByteString->(x->a)->序列化了一个
,它存储了一个ByteString和一个post反序列化函数,并且有一个
Functor
实例。但这当然违背了本文的目的。这与Sculthorpe等人的论文主题密切相关。我还没有把这篇文章放到Hackage上,但库中有一个可以约束函子的参数类型以及函子类型本身的函数。虽然这并不能真正解决我的问题(正如我希望
fmap
重复进行反编码一样),我会接受这个答案b/c我认为我最初的想法是不可能的,这是为受约束的GADT定义函子的最实用的方法。此外。