2016-06-19 56 views
3

我正在寫一個函數,它會接受任意列表,並將它們進行比較以查看其中是否是另一個列表的子列表。對於stdin,我想要求用戶提供兩個列表,但我無法弄清楚接受任意類型的方法。這是我到目前爲止的代碼:如何從Haskell中的任意類型[a]的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 

任何幫助,將不勝感激:

我想有而我只能目前支持一次一個部分的輸入和輸出的例子!

+2

舉幾個例子,說明用戶可能輸入什麼樣的輸入以及您想要將輸入解釋爲什麼類型。 – ErikR

+0

好主意,我在 –

+0

中加入了它們:用戶可以輸入:[[1,2,'cat']'? – ErikR

回答

4

read必須事先知道它正在閱讀什麼樣的東西 - 這就是它的工作方式。

這是而不是read查看字符串以確定返回的類型的情況。例如考慮:

read "1" :: Float 
read "1" :: Int 

第一次讀會返回一個Float(1.0)和第二的INT(1)即使被讀取的字符串是完全一樣的。

你可能會認爲這是從其他語言,如Python,在那裏你可以EVAL "[1,2,3]"和獲取列表和eval "5"得到一個號碼,你不必告訴EVAL返回什麼樣的事情不同。然而,Haskell的答案是這些語言實際上只處理一個類型這是一個和類型,如:

data PyVal = PyNum Int 
      | PyStr String 
      | PyList [ PyVal ] 
      | PyDict [ (PyStr, PyVal) ] 
      | ... 

因此可能表現的宇宙是封閉的。所以,實際上,eval知道它正在閱讀什麼樣的東西。在Haskell中,您始終可以添加新類型,因此可以添加新的閱讀器和顯示功能。

2

您的根本問題是Haskell獨立。簡單地給某人兩個字符串表示值是不足以確定平等的。你必須告訴那個人這些值的解釋應該是什麼,因爲一個字符串可以用多種方式解釋。

例如,假設我給你以下輸入

>>> ['a', 'b'] 
    ['A', 'B'] 

你應該怎麼回報?如果我的意思是用標準的區分大小寫的字符來解釋,那麼我應該回到False。另一方面,如果我使用不區分大小寫的字符(例如,由this package提供),那麼我應該返回True。給我的字符串表示是不明確的。

如果你關心的是字符串表示本身,那麼你的值只是read到字符串列表和使用sublist那些。如果你關心該字符串的解釋,那麼你必須允許用戶指定解釋,或者以某種方式指定解釋代碼(其中@ErikR的ADT編碼和你的類型註釋是兩種可能性)。