问题描述
今天,我想调查是否有可能以这种方式构造数据类型,它不会存储类型签名类型的数据,而是存储它的另一种表示形式。因此,我尝试了一个GADT,它的类型构造函数类型为 a ,但是类型为 ByteString 的数据构造函数>。{ - #LANGUAGE GADTs# - }
import Data.ByteString.Char8
import Data 。序列化
数据序列化a where
MkSerialized ::(Serialize a)=> ByteString - >序列化
现在我可以定义一个 decode'函数按以下方式:
decode'::(Serialize a)=>序列化的a - >
解码'(MkSerialized bs)=让右r =(解码bs)in r
它的工作原理:
$ pre $ let $ s = MkSerialized(encodetest):: Serialized String
print $ decode 's - printstest
现在我的问题是我想要序列化为 Functor 的实例。
$ f $ / code>
但是我得到的错误(序列化b)无法推断。我如何限制Functor实例,以便在 fmap 中实施 Serialize ?
您可以使用 CoYoneda函子完成此操作。 很简单:有一个额外的功能字段,可以累积 fmap ing函数。当你解码你的值,然后应用该函数。
以下是代码:
{ - #LANGUAGE GADTs# - }
import Data.ByteString.Char8
import Data.Serialize
data序列化a其中
MkSerialized
::(序列化a)
=> ByteString - > (a - > b) - >序列化b
解码'::序列化a - > a
decode'(MkSerialized bs f)= let Right r =解码bs in fr
实例Functor序列化其中
fmap f(MkSerialized bs g)= MkSerialized bs(f。 g)
这也有自动融合多个 fmap s而不是重复的解码和编码,就像你的情况一样。
Today I wanted to investigate if it is possible to construct a data type in such a way, that it does not store the data of the type of its type signature, but another representation of it. So, here is my attempt of an GADT which has a type constructor of type a, but a data constructor of type ByteString.
{-# LANGUAGE GADTs #-} import Data.ByteString.Char8 import Data.Serialize data Serialized a where MkSerialized :: (Serialize a) => ByteString -> Serialized a
Now I can define a decode' function in the following way:
decode' :: (Serialize a) => Serialized a -> a decode' (MkSerialized bs) = let Right r = (decode bs) in r
And it works:
let s = MkSerialized (encode "test") :: Serialized String print $ decode' s -- prints "test"
My problem is now that I'd like Serialized to be an instance of Functor.
instance Functor Serialized where fmap f (MkSerialized bs) = MkSerialized (encode (f (right (decode bs)))) where right (Right r) = r
But I get the error (Serialize b) can not be deduced. How can I constraint the Functor instance so that Serialize is enforced in the fmap?
You can do this using a CoYoneda functor.
The idea is simple: have an additional functional field where you accumulate your fmaping functions. When you decode your value, then apply that function.
Here's the code:
{-# 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)
This also has the benefit of automatically fusing multiple fmaps instead of repeated decodings and encodings, as would be in your case.
这篇关于具有类型约束的GADT的Functor实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!