我正在编写一个函数,它接受任意列表并比较它们以查看是否是另一个列表。对于stdin,我想问用户两个列表,但我无法想出一种接受任意类型的方法。到目前为止,这是我的代码:
1 main :: IO ()
2 main = do
3 l1 <- getLine
4 l2 <- getLine
5 print $ sublist (read l1 :: [Int]) (read l2:: [Int])
6
7 sublist :: Eq a => [a] -> [a] -> Bool
8 sublist b p = any ((b ==) . take len) . takeWhile ((len<=) . length) $ iterate tail p
9 where len = length b
我的主要问题是第5
行,我必须为read
选择一种类型。
我想要的一些输入和输出示例,而我目前只能支持一个:
>>> [1,2,3]
[1,2,3,4,5]
True
>>> ["a", "bc"]
["xy", "b", "bc"]
False
>>> [True, False, True]
>>> [False, True, False, True]
True
-- And even nested types
>>> [[1], [2,3]]
[[2,4], [1], [2,3], [4]
True
非常感谢任何帮助!
答案 0 :(得分:4)
read
必须事先知道它正在阅读什么样的东西 - 这就是它的工作方式。
不 read
查看字符串以确定要返回的类型的情况。例如,考虑:
read "1" :: Float
read "1" :: Int
第一次读取将返回Float(1.0),第二次读取将返回Int(1),即使正在读取的字符串完全相同。
您可能认为这与其他语言不同,例如Python,您可以在其中评估"[1,2,3]"
并获取列表并使用eval "5"
来获取数字,而不必告诉eval什么样的回报。但是,Haskell对此的回答是那些语言实际上只处理 one 类型,它是一种总和类型:
data PyVal = PyNum Int
| PyStr String
| PyList [ PyVal ]
| PyDict [ (PyStr, PyVal) ]
| ...
因此,可能的表达式的世界是封闭的。所以,实际上,eval知道它正在阅读什么样的东西。在Haskell中,您始终可以添加新类型,从而添加新的阅读器和显示功能。
答案 1 :(得分:2)
您的基本问题是与Haskell无关。简单地给某人两个字符串表示值不足以确定相等性。你必须告诉那个人这些值的解释应该是什么,因为一个字符串可以用很多方式解释。
例如,让我们说我给你以下输入
>>> ['a', 'b']
['A', 'B']
你应该回报什么?如果我的意思是使用标准区分大小写的字符来解释,那么我应该回到False
。另一方面,如果我使用不区分大小写的字符(例如由this package提供),那么我应该回到True
。只是给我字符串表示是不明确的。
如果您关心的是字符串表示本身,那么只需将read
您的值放入字符串列表中,然后对其使用sublist
。如果您确实关心该字符串的解释,那么您必须允许用户指定该解释,或者以某种方式在代码中指定该解释(其中@ErikR&amp; ADT编码和您的类型注释是两种可能性)