在 Haskell 中,`a` 可以是任何东西吗?
In Haskell, could `a` be anything?
虽然我一直在阅读文档,但我一直认为 a
可以是以下任何内容:
example :: a -> a
'a' 可以是 Char
、String
、Int
、Integer
.
当然,如果我输入:
example :: [a] -> a
输入应该是一个列表,但可以是任何列表:["ab", "cd"]
、[1,2]
或 ['s', 'c']
.
但是在我的代码中:
toString' :: (Show a) => [a] -> String
toString' [] = "empty"
toString' [x] = " and " ++ show x
toString' (x:y:[]) = show x ++ toString' [y]
toString' (x:xs) = show x ++ ", " ++ toString' xs
它应该有效,但并不总是有效:
Prelude> toString' ['a', 'b', 'c'] -- Works
Prelude> toString' [1, 2, 3] -- Don't work
Prelude> toString' ["abc", "bc", "efc"] -- Don't work
我不明白为什么我需要添加 Show
约束,如果通常在本书的示例中我不需要它。
更新
好吧,不是,不是["abc", "bc", "efc]
到["abc", "bc", "efc"]
的变化,其实代码里我写对了,只是这里我先打错了
关于Show
,如果有必要在这段代码中使用它,你能回答我吗?
更新 2
我不知道如果你投反对票它是否有用,或者它会被关闭,但无论如何
如果我在最后一行使用以下代码,代码将运行得更好:
toString' (x:xs) = show x ++ ", " ++ (toString' xs)
但仍然不明白为什么我需要 Show
(我的意思是,为什么我不能从代码中删除它?)
更新 3
我看到 Show
的错误,如果你使用变量类型 a
而不是 String
,你需要 Show
,也许是因为它可以 Haskell 在你输入一个值之前不知道它是哪种类型,所以它需要知道你想要显示它,或者因为有些类型的变量不会自己扩展 Show
.
这不是类型错误,这是 语法 错误。您只是漏掉了行尾的结束引号。
toString' ["abc", "bc", "efc"]
^
我刚刚将您的代码复制到我的 GHCi 中,您的所有三个示例都有效。 Prelude> toString' ["abc", "bc", "efc"]
产生
"\"abc\", \"bc\" and \"efc\""
。
我想发生的事情是你在没有类型签名的情况下在 GHCi 中尝试了你的定义,并且单态限制开始了。这就是为什么只有一个例子 "worked" 适合你。
关于Show
约束,既然你用的是show :: Show a => a -> String
函数,是的,这是必须的。
如果您要定义 特定 版本 toString'Int :: [Int] -> String
(或 Char
),那将没有问题。但是您是为 [a]
定义它——为 any a
。由于您正在使用 show (x :: a)
,因此此函数接受的 any a
必须属于 Show
。这表示为 (Show a) => ....
.
虽然我一直在阅读文档,但我一直认为 a
可以是以下任何内容:
example :: a -> a
'a' 可以是 Char
、String
、Int
、Integer
.
当然,如果我输入:
example :: [a] -> a
输入应该是一个列表,但可以是任何列表:["ab", "cd"]
、[1,2]
或 ['s', 'c']
.
但是在我的代码中:
toString' :: (Show a) => [a] -> String
toString' [] = "empty"
toString' [x] = " and " ++ show x
toString' (x:y:[]) = show x ++ toString' [y]
toString' (x:xs) = show x ++ ", " ++ toString' xs
它应该有效,但并不总是有效:
Prelude> toString' ['a', 'b', 'c'] -- Works
Prelude> toString' [1, 2, 3] -- Don't work
Prelude> toString' ["abc", "bc", "efc"] -- Don't work
我不明白为什么我需要添加 Show
约束,如果通常在本书的示例中我不需要它。
更新
好吧,不是,不是["abc", "bc", "efc]
到["abc", "bc", "efc"]
的变化,其实代码里我写对了,只是这里我先打错了
关于Show
,如果有必要在这段代码中使用它,你能回答我吗?
更新 2
我不知道如果你投反对票它是否有用,或者它会被关闭,但无论如何
如果我在最后一行使用以下代码,代码将运行得更好:
toString' (x:xs) = show x ++ ", " ++ (toString' xs)
但仍然不明白为什么我需要 Show
(我的意思是,为什么我不能从代码中删除它?)
更新 3
我看到 Show
的错误,如果你使用变量类型 a
而不是 String
,你需要 Show
,也许是因为它可以 Haskell 在你输入一个值之前不知道它是哪种类型,所以它需要知道你想要显示它,或者因为有些类型的变量不会自己扩展 Show
.
这不是类型错误,这是 语法 错误。您只是漏掉了行尾的结束引号。
toString' ["abc", "bc", "efc"]
^
我刚刚将您的代码复制到我的 GHCi 中,您的所有三个示例都有效。 Prelude> toString' ["abc", "bc", "efc"]
产生
"\"abc\", \"bc\" and \"efc\""
。
我想发生的事情是你在没有类型签名的情况下在 GHCi 中尝试了你的定义,并且单态限制开始了。这就是为什么只有一个例子 "worked" 适合你。
关于Show
约束,既然你用的是show :: Show a => a -> String
函数,是的,这是必须的。
如果您要定义 特定 版本 toString'Int :: [Int] -> String
(或 Char
),那将没有问题。但是您是为 [a]
定义它——为 any a
。由于您正在使用 show (x :: a)
,因此此函数接受的 any a
必须属于 Show
。这表示为 (Show a) => ....
.