考虑以下情况:
{-# LANGUAGE QuantifiedConstraints #-}
data SomeMaybe c t where
SomeNothing :: SomeMaybe c t
SomeJust :: c t => t -> SomeMaybe c t
instance (forall b. c b => Semigroup b) => Semigroup (SomeMaybe c u) where
x <> y = case x of
SomeNothing -> y
SomeJust x' -> case y of
SomeNothing -> x
SomeJust y' -> SomeJust (x' <> y')
我得到以下错误:
src/Filename.hs: error:
• Could not deduce: c (SomeMaybe c u)
arising from a use of ‘GHC.Base.$dmsconcat’
from the context: forall b. c b => Semigroup b
bound by the instance declaration
at src/Filename.hs
• In the expression: GHC.Base.$dmsconcat @(SomeMaybe c u)
In an equation for ‘GHC.Base.sconcat’:
GHC.Base.sconcat = GHC.Base.$dmsconcat @(SomeMaybe c u)
In the instance declaration for ‘Semigroup (SomeMaybe c u)’
• Relevant bindings include
sconcat :: GHC.Base.NonEmpty (SomeMaybe c u) -> SomeMaybe c u
(bound at src/Filename.hs)
我认为问题是sconcat
和stimes
的默认实现无法进行类型检查。
但是我不太明白为什么会这样。
- 背景说明:*
简单介绍一下为什么要创建像SomeMaybe
这样的类型,我将数据类型设置为"barbies",这样就可以像这样使用bpure
:
instance ApplicativeB f => Semigroup (f MyType) where
(<>) = bzipWith (<>)
instance ApplicativeB f => Monoid (f MyType) where
mempty = bpure mempty
但这只适用于MyType a
是所有a
的幺半群。
编辑:解决方法
将Semigroup
定义更改为:
semigroupOp :: forall c t. (forall b. c b => Semigroup b) => SomeMaybe c t -> SomeMaybe c t -> SomeMaybe c t
semigroupOp x y = case x of
SomeNothing -> y
SomeJust x' -> case y of
SomeNothing -> x
SomeJust y' -> SomeJust (x' <> y')
instance forall c t. (forall b. c b => Semigroup b) => Semigroup (SomeMaybe c t) where
(<>) :: (forall b. c b => Semigroup b) => SomeMaybe c t -> SomeMaybe c t -> SomeMaybe c t
(<>) = semigroupOp
sconcat :: NonEmpty (SomeMaybe c t) -> (SomeMaybe c t)
sconcat (a :| as) = go a as where
go :: SomeMaybe c t -> [SomeMaybe c t] -> SomeMaybe c t
go x = \case
[] -> x
(c : cs) -> semigroupOp x (go c cs)
stimes n = \case
SomeNothing -> SomeNothing
SomeJust x -> SomeJust (stimes n x)
它可以编译这个代码,虽然我不清楚为什么要这么做?特别是,为什么我不能在sconcat
中调用<>
而不是semigroupOp
?
1条答案
按热度按时间g0czyy6m1#
从问题中删除,因为它是答案:
回答我自己的问题,将半群定义改为:
解决了这个问题。