【问题标题】:What is the correct type declaration for this function?此函数的正确类型声明是什么?
【发布时间】:2010-07-14 13:09:12
【问题描述】:

以下函数将不会加载:

charName :: a -> String
charName 'a' = "Alpha"
charName 'b' = "Bravo"
charName 'c' = "Charlie"
charName 'd' = "Delta"
charName 'e' = "Echo"
charName 'f' = "Foxtrot"
charName 'g' = "Golf"
charName 'h' = "Hotel"
charName 'i' = "India"
charName 'j' = "Juliet"
charName 'k' = "Kilo"
charName 'l' = "Lima"
charName 'm' = "mike"
charName 'n' = "November"
charName 'o' = "Oscar"
charName 'p' = "Papa"
charName 'q' = "Quebec"
charName 'r' = "Romeo"
charName 's' = "Sierra"
charName 't' = "Tango"
charName 'u' = "Uniform"
charName 'v' = "Victor"
charName 'w' = "Whiskey"
charName 'x' = "X-ray"
charName 'y' = "Yankee"
charName 'z' = "Zulu"
charName 0 = "Zero"
charName 1 = "One"
charName 2 = "Two"
charName 3 = "Three"
charName 4 = "Four"
charName 5 = "Five"
charName 6 = "Six"
charName 7 = "Seven"
charName 8 = "Eight"
charName 9 = "Nine"
charName x = ""

它给了我以下错误:

[1 of 1] 编译 Main(baby.hs,解释)

baby.hs:41:9: 无法匹配预期类型 a' against inferred typeChar' a' is a rigid type variable bound by the type signature forcharName' at baby.hs:40:12 在模式中:'a' 在 `charName' 的定义中: charName 'a' = "Alpha"

baby.hs:67:9: (Num Char) 没有实例 源自文字 0' at baby.hs:67:9 Possible fix: add an instance declaration for (Num Char) In the pattern: 0 In the definition ofcharName': charName 0 = "Zero" 失败,已加载模块:无。

不知道我怎样才能让它工作。有人有什么想法吗?

【问题讨论】:

  • 你的 0, 1, 2... 8, 9 实际上是数字而不是字符。尝试向它们添加“0”、“1”、“2”,使它们成为字符。
  • 这不应该是社区维基。
  • 如果我想接受数字作为输入怎么办?

标签: haskell


【解决方案1】:

使用新的数据类型

将 Char 或 Int 作为函数参数传递的简单方法是定义一个新的数据类型来封装它们:

data (Num a) => CharOrNum a = C Char | N a

charName (C 'z') = "Zulu"
charName (N 0) = "Zero"

那么你就可以像这样使用它了

ghci> charName $ C 'z'
"Zulu"
ghci> charName $ N 0
"Zero"

通过此更改,charName 的类型为 (Num t) => CharOrNum t -> [Char]

新类型类

另一种方法是为两种参数类型定义一个通用类型类,例如Show

class Nameable a where
  nameit :: a -> String

instance Nameable Char where
  nameit 'z' = "Zulu"
  nameit _ = ""

instance Nameable Integer where
  nameit 0 = "Zero"
  nameit _ = ""

那么你可以这样使用它:

ghci> (nameit 0, nameit 'z')
("Zero","Zulu")

【讨论】:

  • 这就是我要找的。谢谢! :-)
  • 当然 Nameable 与 Either 相同,自己制作,使用预定义的,自己选择...我更喜欢新的类型类版本,从长远来看会变得不那么冗长,并美丽地延伸......
【解决方案2】:

charName不同情况下的参数类型不匹配。有时您使用Char(例如'a'),有时您使用数字(例如9)。

您无法仅通过更改类型签名来完成这项工作。 (嗯,有一种方法:添加一个实例 Num Char,但这是一个非常糟糕的主意)。

实现您打算做的唯一明智的方法是将数字更改为Chars(即'0'而不是0等)。

【讨论】:

  • 我想变坏怎么加一个实例“Num Char”
  • 其实第一个错误并不是因为他把Char和Int混在一起了,而是因为charName被声明为a -> String所以它必须对所有可能的a起作用。
  • djv 我不确定你的意思。我相信我正在用 (charName x = "") 最后解决所有可能的 a's。
  • @djv 是正确的。您不是“解决所有可能的 a”,因为这个单一定义必须适用于每个特定 a,并且它不会进行类型检查,因为大多数类型(即除 Char 之外的所有类型) ) 无法与 Char 进行比较。
  • 事实上,裸类型a 无法与任何东西进行相等性比较。为此,您需要一个 Eq 实例。
【解决方案3】:

好吧,你必须决定参数的类型。字符还是整数? charName 'a'charName 'z' 将 Char 作为参数。 charName 0charName 9 接受一个 Int。和charName x 接受......好吧,任何类型。

我会将charName 0 更改为charName '0' 等 并使用charName _ = "" 匹配任何其他单个字符,除了列出的:

...
charName 'y' = "Yankee"
charName 'z' = "Zulu"
charName '0' = "Zero"
...
charName '9' = "Nine"
charName _ = ""

随着这个变化,函数类型是:charName :: Char -> String

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多