我遇到一个类型的Functor实例有问题,该类型基本上只是嵌套了Either和Maybe。
data Tuple a b = Tuple a b
data Primitive = String String | Boolean Boolean | Number Number | Null
data JsonValue = Object (Map String JsonValue) | Array (List JsonValue) | Primitive
type Path = List String
data JsonGraphValue = JsonGraphObject (Map String JsonGraphValue) | Atom JsonValue | Ref Path | Error JsonValue | JsonPrimitive Primitive
newtype JsonGraphRecResult a = JsonGraphRecResult (Either String (Tuple (Maybe a) (List Path)))
instance jsonGraphRecResultFunctor :: Functor JsonGraphRecResult where
map f (JsonGraphRecResult (Right (Tuple (Just value) paths))) = JsonGraphRecResult (Right (Tuple (Just (f value)) paths))
map f value = value
我收到以下错误,指向上面代码末尾的“value”字。
Could not match type
a1
with type
b0
while trying to match type JsonGraphRecResult a1
with type JsonGraphRecResult b0
while checking that expression value
has type JsonGraphRecResult b0
in value declaration jsonGraphRecResultFunctor
where b0 is a rigid type variable
a1 is a rigid type variable
我不清楚为什么JsonGraphRecResult与以下编译好的Blah类型有任何不同:
newtype Blah a = Blah (Maybe a)
instance blahFunctor :: Functor Blah where
map f (Blah (Just x)) = Blah (Just (f x))
map f value = value
以下gist可以直接粘贴到“Try PureScript”在线REPL中,以便复制错误。
答案 0 :(得分:0)
找出问题所在。在Either为Left的情况下,我不能简单地返回map函数的输入值,因为输入值不是正确的类型。这是问题的简化版本。
-- This is wrong because value is a Functor a, whereas map must return Functor b
map value@Nothing f = value
-- This is right, because even though both sides are Nothing, the right-hand side is a Maybe b vs. Maybe a
map Nothing f = Nothing
答案 1 :(得分:0)
您应该能够为您的类型派生Functor
个实例。但是,在为最终类型派生实例之前,您应该为Tuple
类型派生它(或者只使用Tuple
中的Data.Tuple
; - )):
data Tuple a b = Tuple a b
derive instance functorTuple :: Functor (Tuple a)
正如您所看到的,Functor
实例只能为类型* -> *
定义,因此在这种情况下,我们可以map
超过类型占用"最后位置"在Tuple
。
为了导出JsonGraphRecResult
的实例,您必须更改其内部Tuple
中的类型顺序才能实现"最后位置"要求:
newtype JsonGraphRecResult a =
JsonGraphRecResult (Either String (Tuple (List Path) (Maybe a)))
derive instance functorJsonGraphRecResult :: Functor JsonGraphRecResult
Here是trypurescript.org上相关的交互式代码段,因此您可以使用此实现。
您可以使用此衍生机制的更多类型类:Ord
,Eq
,Generic
,Newtype
...
在这种情况下也值得指出的是,在Purescript中你有额外的派生选项,即" newtype derivedving"。它的语法略有不同,因为它在newtype
之后包含derive
个关键字 - 例如:
derive newtype instance someClassMyType :: SomeClass MyType
Newtype derived用于newtype
"包装"用于派生给定newtype内部类型的类的实例已经定义了实例。换句话说,如果您有newtype T = T a
,则可以为T
具有a
实例的每个类派生Data.Generic.Rep
的新类型实例。
还有另一种策略 - 您还可以使用为Generic
中的某些类型类定义的方法的泛型实现。这些实现可用于{{1}}类实例的类型......但这是另一个故事; - )
您可以在菲尔" 24天的Purescript"中找到更多关于推导的信息。系列: