本文介绍了具有类型约束的GADT的Functor实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

今天,我想调查是否有可能以这种方式构造数据类型,它不会存储类型签名类型的数据,而是存储它的另一种表示形式。因此,我尝试了一个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实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 15:44