我目前正在学习 Haskell 中的类型类,现在我正在尝试创建一个适用于 Maybe 和 Num 的增量函数。但是,我现在有点卡住了。有人可以帮助我朝着正确的方向发展吗?(以下错误)
编辑:我在编译期间按照编译器的建议使用 -XUndecidableInstances 和 -XFlexibleInstances 作为参数,考虑到 -XOverlappingInstances(如评论中所建议)均已弃用且似乎不起作用。
-- maybenum.hs
class SomeNum a where
inc' :: a -> Int
instance Num a => SomeNum a where
inc' n = inc' (Just n)
instance Num a => SomeNum (Maybe a) where
inc' Nothing = 1
inc' (Just n) = n + 1
main :: IO ()
main = do
print $ inc' (Just 0)
print $ inc' 5
print $ inc' Nothing
这是我得到的错误:
[1 of 1] Compiling Main ( maybenum.hs, maybenum.o )
maybenum.hs:5:12: error:
• Overlapping instances for SomeNum (Maybe a)
arising from a use of ‘inc'’
Matching instances:
instance Num a => SomeNum a -- Defined at maybenum.hs:4:10
instance Num a => SomeNum (Maybe a) -- Defined at maybenum.hs:7:10
• In the expression: inc' (Just n)
In an equation for ‘inc'’: inc' n = inc' (Just n)
In the instance declaration for ‘SomeNum a’
maybenum.hs:9:19: error:
• Couldn't match expected type ‘Int’ with actual type ‘a’
‘a’ is a rigid type variable bound by
the instance declaration at maybenum.hs:7:10
• In the expression: n + 1
In an equation for ‘inc'’: inc' (Just n) = n + 1
In the instance declaration for ‘SomeNum (Maybe a)’
• Relevant bindings include
n :: a (bound at maybenum.hs:9:14)
inc' :: Maybe a -> Int (bound at maybenum.hs:8:3)
maybenum.hs:13:11: error:
• Overlapping instances for SomeNum (Maybe a1)
arising from a use of ‘inc'’
Matching instances:
instance Num a => SomeNum a -- Defined at maybenum.hs:4:10
instance Num a => SomeNum (Maybe a) -- Defined at maybenum.hs:7:10
• In the second argument of ‘($)’, namely ‘inc' (Just 0)’
In a stmt of a 'do' block: print $ inc' (Just 0)
In the expression:
do { print $ inc' (Just 0);
print $ inc' 5;
print $ inc' Nothing }
maybenum.hs:13:22: error:
• Ambiguous type variable ‘a1’ arising from the literal ‘0’
prevents the constraint ‘(Num a1)’ from being solved.
Probable fix: use a type annotation to specify what ‘a1’ should be.
These potential instances exist:
instance Num Integer -- Defined in ‘GHC.Num’
instance Num Double -- Defined in ‘GHC.Float’
instance Num Float -- Defined in ‘GHC.Float’
...plus two others
(use -fprint-potential-instances to see them all)
• In the first argument of ‘Just’, namely ‘0’
In the first argument of ‘inc'’, namely ‘(Just 0)’
In the second argument of ‘($)’, namely ‘inc' (Just 0)’
maybenum.hs:14:11: error:
• Overlapping instances for SomeNum a0 arising from a use of ‘inc'’
Matching instances:
instance Num a => SomeNum a -- Defined at maybenum.hs:4:10
instance Num a => SomeNum (Maybe a) -- Defined at maybenum.hs:7:10
(The choice depends on the instantiation of ‘a0’
To pick the first instance above, use IncoherentInstances
when compiling the other instance declarations)
• In the second argument of ‘($)’, namely ‘inc' 5’
In a stmt of a 'do' block: print $ inc' 5
In the expression:
do { print $ inc' (Just 0);
print $ inc' 5;
print $ inc' Nothing }
maybenum.hs:14:16: error:
• Ambiguous type variable ‘a0’ arising from the literal ‘5’
prevents the constraint ‘(Num a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance Num Integer -- Defined in ‘GHC.Num’
instance Num Double -- Defined in ‘GHC.Float’
instance Num Float -- Defined in ‘GHC.Float’
...plus two others
(use -fprint-potential-instances to see them all)
• In the first argument of ‘inc'’, namely ‘5’
In the second argument of ‘($)’, namely ‘inc' 5’
In a stmt of a 'do' block: print $ inc' 5
maybenum.hs:15:11: error:
• Overlapping instances for SomeNum (Maybe a2)
arising from a use of ‘inc'’
Matching instances:
instance Num a => SomeNum a -- Defined at maybenum.hs:4:10
instance Num a => SomeNum (Maybe a) -- Defined at maybenum.hs:7:10
• In the second argument of ‘($)’, namely ‘inc' Nothing’
In a stmt of a 'do' block: print $ inc' Nothing
In the expression:
do { print $ inc' (Just 0);
print $ inc' 5;
print $ inc' Nothing }
这是调整后的代码:
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
class SomeNum a where
inc' :: a -> Int
instance {-# OVERLAPPABLE #-} Integral a => SomeNum a where
inc' n = fromIntegral n + 1
instance Integral a => SomeNum (Maybe a) where
inc' Nothing = 1
inc' (Just n) = fromIntegral n + 1
这正如我认为你的意图:
λ> inc' 1
2
λ> inc' (Just 1)
2
λ> inc' Nothing
1
我根据我认为您对这段代码的意图进行了一些更改。以下是对每个的解释:
{-# OVERLAPPABLE #-}
::您说它已-XOverlappingInstances
被弃用是正确的,但您没有注意到它已被弃用而支持{#- OVERLAPPABLE #-}
. 这是我添加的内容:
instance {-# OVERLAPPABLE #-} (...)
这是一个必要的补充,因为您已经定义了一个单独的Num
for实例Maybe
,这会导致您遇到冲突。对于我所做的更改,这实际上不是必需的,但是如果您确实将限制从 更改回Integral
到Num
再次,这将挽救您的跌倒。
Integral a =>
您不能只是从 a 转换Num
为 an Int
,正如您的inc'
函数所暗示的那样(请记住,这Float
是 的一个实例Num
。)因此,我调整了限制:
instance {-# OVERLAPPABLE #-} Integral a => SomeNum a where
inc' n = fromIntegral n + 1
这也显着简化了inc'
实现。注意使用fromIntegral :: (Integral a, Num b) => a -> b
. 我不完全确定这是否是有意的,但我你没有指定,所以我猜。
我希望这有帮助。如果这不完全符合您的预期,请尝试自行调整并探索这些语言扩展的行为方式。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句