类似 Printf 的函数
Printf-like function
我正在尝试编写一个具有任意数量参数的函数。这些参数可以是 Int 或 String。我对整数有疑问。由于某种原因(我不明白),值 1 成为歧义的来源。如何处理这个错误,它的来源是什么?
{-# LANGUAGE FlexibleInstances #-}
import Data.Typeable
data PackArgTypes = PackInt Int | PackString String
deriving Show
class PackArg t where
toPackArg :: t -> PackArgTypes
instance PackArg Int where
toPackArg = PackInt . fromIntegral
instance PackArg Integer where
toPackArg = PackInt . fromIntegral
instance PackArg String where
toPackArg = PackString
class PackType t where
pack' :: String -> [PackArgTypes] -> t
instance PackType (IO a) where
pack' fmt acc = do
print fmt
mapM_ print acc
return undefined
instance (PackArg a, PackType r) => PackType (a -> r) where
pack' fmt acc = \x -> pack' fmt $ acc ++ [toPackArg x]
pack :: (PackType t) => String -> t
pack fmt = pack' fmt []
main :: IO ()
main = do
pack "asd" "qwe" "asd"(1 :: Int) -- Ok
pack "asd" "qwe" "asd" 1 -- Sad
在上述情况下我遇到了错误
test1.hs:33:3-6: No instance for (PackArg a0) arising from a use of ‘pack’ …
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
instance PackArg String
-- Defined at /home/knesterov/test1.hs:13:10
instance PackArg Int -- Defined at /home/knesterov/test1.hs:10:10
In a stmt of a 'do' block: pack "asd" "qwe" "asd" 1
In the expression: do { pack "asd" "qwe" "asd" 1 }
In an equation for ‘main’: main = do { pack "asd" "qwe" "asd" 1 }
test1.hs:33:26: No instance for (Num a0) arising from the literal ‘1’ …
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
instance Num Double -- Defined in ‘GHC.Float’
instance Num Float -- Defined in ‘GHC.Float’
instance Integral a => Num (GHC.Real.Ratio a)
-- Defined in ‘GHC.Real’
...plus 7 others
In the fourth argument of ‘pack’, namely ‘1’
In a stmt of a 'do' block: pack "asd" "qwe" "asd" 1
In the expression: do { pack "asd" "qwe" "asd" 1 }
Compilation failed.
编辑
感谢 user5402 指出了 ghci 和 ghc 之间的区别。 Ghci 通过 default
启用扩展 ExtendedDefaultRules
因此,我的示例使用了另外三行,没有出现任何错误。
{-# LANGUAGE ExtendedDefaultRules #-}
instance PackArg Integer where
toPackArg = PackInt . fromIntegral
问题在这里:
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
instance Num Double -- Defined in ‘GHC.Float’
instance Num Float -- Defined in ‘GHC.Float’
...
回想一下,文字 1
可以解释为任何 Num
类型的值,因此 GHC 不知道 select 是哪一个 - 例如Int
、Double
、Rational
等
标准Text.Printf
模块有同样的问题:
import Text.Printf
main = putStrLn $ printf "%d" 3
给出同样的错误。
请注意,如果将此代码输入到 ghci 中不会出现错误,因为有默认规则使表达式 1
是单态的而不是多态的。
我正在尝试编写一个具有任意数量参数的函数。这些参数可以是 Int 或 String。我对整数有疑问。由于某种原因(我不明白),值 1 成为歧义的来源。如何处理这个错误,它的来源是什么?
{-# LANGUAGE FlexibleInstances #-}
import Data.Typeable
data PackArgTypes = PackInt Int | PackString String
deriving Show
class PackArg t where
toPackArg :: t -> PackArgTypes
instance PackArg Int where
toPackArg = PackInt . fromIntegral
instance PackArg Integer where
toPackArg = PackInt . fromIntegral
instance PackArg String where
toPackArg = PackString
class PackType t where
pack' :: String -> [PackArgTypes] -> t
instance PackType (IO a) where
pack' fmt acc = do
print fmt
mapM_ print acc
return undefined
instance (PackArg a, PackType r) => PackType (a -> r) where
pack' fmt acc = \x -> pack' fmt $ acc ++ [toPackArg x]
pack :: (PackType t) => String -> t
pack fmt = pack' fmt []
main :: IO ()
main = do
pack "asd" "qwe" "asd"(1 :: Int) -- Ok
pack "asd" "qwe" "asd" 1 -- Sad
在上述情况下我遇到了错误
test1.hs:33:3-6: No instance for (PackArg a0) arising from a use of ‘pack’ …
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
instance PackArg String
-- Defined at /home/knesterov/test1.hs:13:10
instance PackArg Int -- Defined at /home/knesterov/test1.hs:10:10
In a stmt of a 'do' block: pack "asd" "qwe" "asd" 1
In the expression: do { pack "asd" "qwe" "asd" 1 }
In an equation for ‘main’: main = do { pack "asd" "qwe" "asd" 1 }
test1.hs:33:26: No instance for (Num a0) arising from the literal ‘1’ …
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
instance Num Double -- Defined in ‘GHC.Float’
instance Num Float -- Defined in ‘GHC.Float’
instance Integral a => Num (GHC.Real.Ratio a)
-- Defined in ‘GHC.Real’
...plus 7 others
In the fourth argument of ‘pack’, namely ‘1’
In a stmt of a 'do' block: pack "asd" "qwe" "asd" 1
In the expression: do { pack "asd" "qwe" "asd" 1 }
Compilation failed.
编辑
感谢 user5402 指出了 ghci 和 ghc 之间的区别。 Ghci 通过 default
启用扩展 ExtendedDefaultRules因此,我的示例使用了另外三行,没有出现任何错误。
{-# LANGUAGE ExtendedDefaultRules #-}
instance PackArg Integer where
toPackArg = PackInt . fromIntegral
问题在这里:
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
instance Num Double -- Defined in ‘GHC.Float’
instance Num Float -- Defined in ‘GHC.Float’
...
回想一下,文字 1
可以解释为任何 Num
类型的值,因此 GHC 不知道 select 是哪一个 - 例如Int
、Double
、Rational
等
标准Text.Printf
模块有同样的问题:
import Text.Printf
main = putStrLn $ printf "%d" 3
给出同样的错误。
请注意,如果将此代码输入到 ghci 中不会出现错误,因为有默认规则使表达式 1
是单态的而不是多态的。