2010-07-29 40 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