为什么定义 Choice 的实例失败且值未知?
Why is defining an instance of Choice failing with unknown value?
更新:我在这里内联代码。
我正在尝试定义 Data.Profunctor.Choice
的实例,其中 right
是通过调用 left
定义的,但出于某种原因,编译器抱怨 left
未知.
newtype StateTrans s i o = ST (Tuple s i → Tuple s o)
instance stFunctor ∷ Functor (StateTrans s a) where
map f (ST st) = ST $ second f <<< st
instance stProfunctor ∷ Profunctor (StateTrans s) where
dimap f g (ST st) = ST $ second g <<< st <<< second f
instance stChoice ∷ Choice (StateTrans s) where
left (ST f) = ST lf
where
lf (Tuple s (Left a)) = let (Tuple s' b) = f (Tuple s a)
in Tuple s' (Left b)
lf (Tuple s (Right c)) = Tuple s (Right c)
-- Fails to compile with: Unknown value left
right f = arr mirror <<< left f <<< arr mirror
where
mirror Left x = Right x
mirror Right x = Left x
可能是个愚蠢的错误,但我已经查看我的代码很长时间了,我无法弄清楚哪里出了问题。
(次要且不相关:在 left
的 Right
情况下,我必须解包并重新打包该值,以便它类型对齐。添加类型归属也无法编译.)
奇怪的是,我对 Strong
做同样的事情没有问题,请参阅:
instance stStrong ∷ Strong (StateTrans s) where
first (ST f) = ST ff
where
ff (Tuple s (Tuple a c)) = let (Tuple s' b) = f $ Tuple s a
in Tuple s' (Tuple b c)
second f = arr swap <<< first f <<< arr swap
首先,要使用 arr
,您需要为 StateTrans s
声明 Category
实例:
instance stSemigroupoid :: Semigroupoid (StateTrans s) where
compose (ST f1) (ST f2) = ST $ f1 <<< f2
instance stCategory :: Category (StateTrans s) where
id = ST $ \x -> x
对于第二步,我需要添加更多类型注释(不确定为什么需要它们,但这样构建成功了):
choiceLeft :: forall input output a s. (StateTrans s) input output -> (StateTrans s) (Either input a) (Either output a)
choiceLeft (ST f) = ST lf
where
lf (Tuple s (Left a)) = let (Tuple s' b) = f (Tuple s a)
in Tuple s' (Left b)
lf (Tuple s (Right c)) = Tuple s (Right c)
choiceRight :: forall input output t s. (StateTrans s) input output -> (StateTrans s) (Either t input) (Either t output)
choiceRight f = amirror <<< choiceLeft f <<< amirror
where
mirror :: forall a b. Either a b -> Either b a
mirror (Left x) = Right x
mirror (Right x) = Left x
amirror :: forall a b. StateTrans s (Either b a) (Either a b)
amirror = arr mirror
instance stChoice ∷ Choice (StateTrans s) where
left = choiceLeft
right = choiceRight
注意:使用 PureScript
版本 0.11.7
和 purescript-profunctor
版本 3.2.0
。
我不是 100% 确定,因为粘贴的代码段不包含导入,但我怀疑您有 Data.Profunctor.Choice (class Choice)
而不是 Data.Profunctor.Choice (class Choice, left, right)
.
的导入
导入 class 不会隐式导入其成员,即使不这样做也可以在实例中定义它们。
更新:我在这里内联代码。
我正在尝试定义 Data.Profunctor.Choice
的实例,其中 right
是通过调用 left
定义的,但出于某种原因,编译器抱怨 left
未知.
newtype StateTrans s i o = ST (Tuple s i → Tuple s o)
instance stFunctor ∷ Functor (StateTrans s a) where
map f (ST st) = ST $ second f <<< st
instance stProfunctor ∷ Profunctor (StateTrans s) where
dimap f g (ST st) = ST $ second g <<< st <<< second f
instance stChoice ∷ Choice (StateTrans s) where
left (ST f) = ST lf
where
lf (Tuple s (Left a)) = let (Tuple s' b) = f (Tuple s a)
in Tuple s' (Left b)
lf (Tuple s (Right c)) = Tuple s (Right c)
-- Fails to compile with: Unknown value left
right f = arr mirror <<< left f <<< arr mirror
where
mirror Left x = Right x
mirror Right x = Left x
可能是个愚蠢的错误,但我已经查看我的代码很长时间了,我无法弄清楚哪里出了问题。
(次要且不相关:在 left
的 Right
情况下,我必须解包并重新打包该值,以便它类型对齐。添加类型归属也无法编译.)
奇怪的是,我对 Strong
做同样的事情没有问题,请参阅:
instance stStrong ∷ Strong (StateTrans s) where
first (ST f) = ST ff
where
ff (Tuple s (Tuple a c)) = let (Tuple s' b) = f $ Tuple s a
in Tuple s' (Tuple b c)
second f = arr swap <<< first f <<< arr swap
首先,要使用 arr
,您需要为 StateTrans s
声明 Category
实例:
instance stSemigroupoid :: Semigroupoid (StateTrans s) where
compose (ST f1) (ST f2) = ST $ f1 <<< f2
instance stCategory :: Category (StateTrans s) where
id = ST $ \x -> x
对于第二步,我需要添加更多类型注释(不确定为什么需要它们,但这样构建成功了):
choiceLeft :: forall input output a s. (StateTrans s) input output -> (StateTrans s) (Either input a) (Either output a)
choiceLeft (ST f) = ST lf
where
lf (Tuple s (Left a)) = let (Tuple s' b) = f (Tuple s a)
in Tuple s' (Left b)
lf (Tuple s (Right c)) = Tuple s (Right c)
choiceRight :: forall input output t s. (StateTrans s) input output -> (StateTrans s) (Either t input) (Either t output)
choiceRight f = amirror <<< choiceLeft f <<< amirror
where
mirror :: forall a b. Either a b -> Either b a
mirror (Left x) = Right x
mirror (Right x) = Left x
amirror :: forall a b. StateTrans s (Either b a) (Either a b)
amirror = arr mirror
instance stChoice ∷ Choice (StateTrans s) where
left = choiceLeft
right = choiceRight
注意:使用 PureScript
版本 0.11.7
和 purescript-profunctor
版本 3.2.0
。
我不是 100% 确定,因为粘贴的代码段不包含导入,但我怀疑您有 Data.Profunctor.Choice (class Choice)
而不是 Data.Profunctor.Choice (class Choice, left, right)
.
导入 class 不会隐式导入其成员,即使不这样做也可以在实例中定义它们。