haskell - typeclass with constrained params' function
问题描述
I want to write a class like this:
class C c where
op :: c -> c -> Bool
class A b => B b where
func :: C c => b -> c -- ^ type 'c' is random(forall).
func2 :: b -> b -> Bool
func2 x y = func b `op` func c
Here, c
is a type restricted by C
and this restriction will be used in func2.
But this cannot be compiler. Type c
is not a real type. I try to add forall
or using TypeFamilies
, but none of them can do this. TypeFamilies
looks good, but it cannot use with restriction in funcion definition like C c => b -> c
or `type X x :: C * => *.
Must I use (A b, C c) => B b c
to define this class? I have another class using with B like B b => D d b
. If adding a param for class B, the D class needs one more param as well. In fact, Seq a
will be used with class D
, which cannot match D d b
.
EDIT: one more description.
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
module Main where
type Ta = (Integer, Integer)
newtype Tb t = Tb { tb :: [t] } deriving Show
class Eq a => A a where
a1f :: Ord b => a -> b
a2f :: a -> a -> Bool
a2f x y = a1f x >= a1f y
instance A Ta where
a1f (_, y) = y
class A a => B b a where
op :: b a -> b a
instance B Tb Ta where
op x = x
main :: IO ()
main = putStrLn $ show $ op $ (Tb [(1, 1)] :: Tb Ta)
Compiler will complain with the line a2f :: b -> Bool
:
• Could not deduce (Ord a0) arising from a use of ‘>=’
from the context: A a
bound by the class declaration for ‘A’ at test.hs:10:15
The type variable ‘a0’ is ambiguous
These potential instances exist:
instance Ord Ordering -- Defined in ‘GHC.Classes’
instance Ord Integer
-- Defined in ‘integer-gmp-1.0.2.0:GHC.Integer.Type’
instance Ord a => Ord (Maybe a) -- Defined in ‘GHC.Maybe’
...plus 22 others
...plus four instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the expression: a1f x >= a1f y
In an equation for ‘a2f’: a2f x y = a1f x >= a1f y
EDIT2: Use type families
...
class Eq a => A a where
type AT a :: *
a1f :: Ord (AT a) => a -> AT a
a2f :: a -> a -> Bool
a2f x y = a1f x >= a2f y
instance A Ta where
type AT Ta = Integer
a1f (_, y) = y
...
It will show error with:
• Could not deduce (Ord (AT a)) arising from a use of ‘>=’
from the context: A a
bound by the class declaration for ‘A’ at test.hs:10:15
• In the expression: a1f x >= a1f y
In an equation for ‘a2f’: a2f x y = a1f x >= a1f y
解决方案
在您的代码中,问题只是c
in func b `op` func c
is ambiguous。这并不是什么大问题:只需使用本地签名确定选择即可。例如
func2 x y = func x `op` (func y :: Int)
但这可能不是你真正想要的。c
真的应该是类的类型参数,func
还是整个实例的类型参数?在后一种情况下,MPTC 将是正确的方法。
{-# LANGUAGE MultiParamTypeClasses, AllowAmbiguousTypes, TypeApplications #-}
class ∀ b c . (A b, C c) => B b c where
func :: b -> c
func2 :: b -> b -> Bool
func2 x y = func @b @c b `op` func c
或者,如果对于每个实例,只有一个c
有意义,那么您需要一个类型系列或基金。
{-# LANGUAGE TypeFamilies #-}
class A b => B b where
type Ct b :: *
func :: b -> Ct b
func2 :: b -> b -> Bool
func2 x y = func b `op` func c
推荐阅读
- react-native - Reactnative:安装expo-cli时出现代码ELIFECYCLE错误
- python - 为什么在导入 matplotlib.pyplot 时出现“ModuleNotFoundError:没有名为 matplotlib.mathtext 的模块”?
- c# - NonConcurrentGC 代替 ForegroundGC
- php - 在 php Symfony 中向 csv 导出添加行标题
- php - 在 PHP 中从 MySQL 获取数据
- c# - 将 JSON 反序列化为字典
> - python - Selenium Python - 可以定位表(带回编号行/列)但找不到要单击的特定元素
- delegates - 自定义委托过滤器 VC Swift5
- html - 仅在超过一定长度时显示 div
- gnuplot - 指数函数 - 绘制最小值