繁体   English   中英

针对具有Show约束的Maybe模式匹配时,Haskell中的类型错误

[英]Type error in Haskell when pattern matching against Maybe with Show constraint

import Data.Maybe

f :: (Show t) => Maybe t -> IO () 
f Nothing  = putStrLn   "Nothing!"
f (Just x) = putStrLn $ "The number is " ++ (show x)

main = do
  f Nothing

这给出:

foo.hs:7:3:
    No instance for (Show a0) arising from a use of ‘f’
    The type variable ‘a0’ is ambiguous
    Note: there are several potential instances:
      instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’
      instance Show Ordering -- Defined in ‘GHC.Show’
      instance Show Integer -- Defined in ‘GHC.Show’
      ...plus 22 others
    In a stmt of a 'do' block: f Nothing
    In the expression: do { f Nothing }
    In an equation for ‘main’: main = do { f Nothing }

foo.hs:7:3:
    No instance for (Show a0) arising from a use of ‘f’
    The type variable ‘a0’ is ambiguous
    Note: there are several potential instances:
      instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’
      instance Show Ordering -- Defined in ‘GHC.Show’
      instance Show Integer -- Defined in ‘GHC.Show’
      ...plus 22 others
    In a stmt of a 'do' block: f Nothing
    In the expression: do { f Nothing }
    In an equation for ‘main’: main = do { f Nothing }

如何解决这种代码和平问题? 重点是安全地打印可显示的内容。 我认为(Show t)=>也许t可以被分解为Nothing和Just x。

假设您是编译器,并且您正在尝试键入检查程序:

main = do
 f Nothing

你懂的:

  1. main必须具有IO ()类型,因为这是编译器强加的要求;
  2. f必须具有类型(Show t) => Maybe t -> IO () ,因为这是它的类型注释。
  3. Nothing必须有类型Maybe a ,其中, a = t (相同t如在使用f );
  4. 因此, a必须是Show实例。

但是,这还不足以使程序得以编译,Haskell必须在您的main动作中对f的调用进行单态化 ,即找出在f特定用法中每个类型变量的具体类型。 在这种情况下,这是因为main :: IO ()类型是单态的(其中没有类型变量),因此在其定义中出现的所有表达式都不能具有未实例化的类型变量。

这就是模棱两可的类型错误的含义:您的程序没有足够的信息供编译器确定对f的调用的Maybe参数的元素类型。 可以确定的是它必须是Show实例,但这还不足以使程序可以编译。

解决方案是在某个位置添加类型注释,以便为其选择具体类型。 有很多方法:

main = f (Nothing :: Maybe Int)

main = f argument
  where argument :: Maybe Integer
        argument = Nothing

main = (f :: Maybe String -> IO ()) Nothing

之所以只有一种方式,是因为类型推断就像侦探一样,它通过汇集许多不同的线索而起作用,因此,您可以提供许多不同的提示,以使其“解决问题”。 ”

这里Nothing任何可能的Maybe a ,你必须指定a你的意思是-尝试

main :: IO ()
main = f (Nothing :: Maybe Int)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM