在这个例子中有没有办法避免 UndecidableInstances?
Is there a way to avoid UndecidableInstances in this example?
当我尝试这个时:
import GHC.Generics (Generic)
import Control.DeepSeq (NFData(..))
import Data.Vector.Generic (Vector)
data Entry a = Entry !Bool a
deriving (Generic, NFData)
-- The variable @v@ is meant to be instantiated with a 'Vector'
-- type. Most operations for the type have a @Vector v (Entry a)@
-- constraint.
newtype DenseIntMap v a = DenseIntMap (v (Entry a))
instance NFData (v (Entry a)) => NFData (DenseIntMap v a) where
rnf (DenseIntMap va) = rnf va
...我收到此错误:
/Users/casillas/GitHub/tau-sigma/src/TauSigma/Util/DenseIntMap.hs:53:10:
Constraint is no smaller than the instance head
in the constraint: Vector v (Entry a)
(Use UndecidableInstances to permit this)
In the instance declaration for ‘NFData (DenseIntMap v a)’
/Users/casillas/GitHub/tau-sigma/src/TauSigma/Util/DenseIntMap.hs:53:10:
Constraint is no smaller than the instance head
in the constraint: NFData (v (Entry a))
(Use UndecidableInstances to permit this)
In the instance declaration for ‘NFData (DenseIntMap v a)’
使用 UndecidableInstances
确实可以让它消失,但我对使用该扩展持谨慎态度。在这种情况下还有其他方法可以使事情正常进行吗? (最好不要过多更改类型。)
警告:我还没有测试过任何这段代码。
对我来说最干净的方法是遵循 Prelude.Extras
风格的路径:
class NFData1 f where
rnf1 :: NFData a => f a -> ()
您现在可以为每种向量类型编写类似
的内容
instance NFData1 V where
rnf1 = rnf
然后
instance (NFData1 v, NFData a) => NFData (DenseIntMap v a) where ...
另一种可能更适合您当前代码的替代方法是明确地将 v
视为 Vector
。与其担心 v a
会如何强迫自己,不如通过折叠将你自己的想法压在喉咙里:比如
instance (Vector v a, NFData a) => NFData (DenseIntMap v a) where
rnf = V.foldl' (\() e -> rnf e) ()
第二种方法似乎不太适合向量融合,除非您仔细考虑要从左到右和从右到左强制哪些向量。
当我尝试这个时:
import GHC.Generics (Generic)
import Control.DeepSeq (NFData(..))
import Data.Vector.Generic (Vector)
data Entry a = Entry !Bool a
deriving (Generic, NFData)
-- The variable @v@ is meant to be instantiated with a 'Vector'
-- type. Most operations for the type have a @Vector v (Entry a)@
-- constraint.
newtype DenseIntMap v a = DenseIntMap (v (Entry a))
instance NFData (v (Entry a)) => NFData (DenseIntMap v a) where
rnf (DenseIntMap va) = rnf va
...我收到此错误:
/Users/casillas/GitHub/tau-sigma/src/TauSigma/Util/DenseIntMap.hs:53:10:
Constraint is no smaller than the instance head
in the constraint: Vector v (Entry a)
(Use UndecidableInstances to permit this)
In the instance declaration for ‘NFData (DenseIntMap v a)’
/Users/casillas/GitHub/tau-sigma/src/TauSigma/Util/DenseIntMap.hs:53:10:
Constraint is no smaller than the instance head
in the constraint: NFData (v (Entry a))
(Use UndecidableInstances to permit this)
In the instance declaration for ‘NFData (DenseIntMap v a)’
使用 UndecidableInstances
确实可以让它消失,但我对使用该扩展持谨慎态度。在这种情况下还有其他方法可以使事情正常进行吗? (最好不要过多更改类型。)
警告:我还没有测试过任何这段代码。
对我来说最干净的方法是遵循 Prelude.Extras
风格的路径:
class NFData1 f where
rnf1 :: NFData a => f a -> ()
您现在可以为每种向量类型编写类似
的内容instance NFData1 V where
rnf1 = rnf
然后
instance (NFData1 v, NFData a) => NFData (DenseIntMap v a) where ...
另一种可能更适合您当前代码的替代方法是明确地将 v
视为 Vector
。与其担心 v a
会如何强迫自己,不如通过折叠将你自己的想法压在喉咙里:比如
instance (Vector v a, NFData a) => NFData (DenseIntMap v a) where
rnf = V.foldl' (\() e -> rnf e) ()
第二种方法似乎不太适合向量融合,除非您仔细考虑要从左到右和从右到左强制哪些向量。