2010-07-29 65 views
6

read在前奏定義爲Haskell中:讀取和類型簽名

read :: (Read a) => String -> a 

和可被用作例如read "1" :: Int

現在的功能

readOne :: (Read a) => [String] -> (a, [String]) 
readOne (x:xs) = (read x,xs) 

readOne ["1","foo"]結果(如預期)錯誤

Ambiguous type variable 'a' in the constraint:
'Read a' arising from a use of 'readOne' at :1:0-18
Probable fix: add a type signature that fixes these type variable(s)

readOne ["1","foo"] :: Int不工作使用,而

readOneInt :: [String] -> (Int, [String]) 
readOneInt = readOne 

作品就好:

> readOneInt ["1", "foo"] 
(1,["foo"]) 

所以:我怎麼可以添加一個類型簽名readOne沒有定義像readOneInt新功能?

回答

9

readOne ["1","foo"] :: Int不起作用,因爲readOne不可能返回Int,它總是返回一個元組,第二個元素是[String]readOne ["1", "foo"] :: (Int, [String])將工作。

請注意,只有在無法推斷的情況下才需要指定類型。如果在Int需要使用readOne的情況下,可以使用readOne而不使用類型註釋。例如:

let inc (i, strs) = (i + 1, strs) in 
inc (readOne ["1", "foo"]) 
-- (2, ["foo"]) 
+0

非常感謝! – 2010-07-29 12:19:43

+2

小心!最後的例子只能用於ghci,因爲1的類型默認爲'Integer'。如果你詢問ghci表達式的類型(通過':t'),你會得到'(Num a,Read a)=>(a,[String])',它具有與以前相同的問題。 asTypeOf(readOne [「1」,「foo」])(0 :: Double,[] :: [String])' - 我通常在反引號中用asTypeOf寫入,但as不喜歡雙引號反引號。 – yatima2975 2010-07-29 14:24:53