2

我有这个:

 get3th (_,_,a,_,_,_) = a

这在 GHCI 中工作正常,但我想用 GHC 编译它,它给出了错误。如果我想编写一个函数来获取元组的第 n 个元素并能够在 GHC 中运行,我该怎么办?我的所有程序如下所示,我该怎么办?

 get3th (_,_,a,_,_,_) = a


 main = do 

    mytuple  <- getLine 
    print $  get3th mytuple
4

3 回答 3

0

getLine 的类型是IO String,因此您的程序不会键入检查,因为您提供的是 aString而不是元组。

如果提供了正确的参数,您的程序将运行,即:

main = do 
  print $  get3th (1, 2, 3, 4, 5, 6)
于 2013-10-07T11:19:02.847 回答
0

你的问题是getLine给你一个String,但你想要某种元组。您可以通过将 转换为元组来解决您的问题String——例如使用内置read函数。这里的第三行试图将 s 解析String为 s 的六元组Int

main = do
  mystring <- getLine

  let mytuple = read mystring :: (Int, Int, Int, Int, Int, Int)

  print $ get3th mytuple

但是请注意,虽然这对于学习类型等很有用,但您永远不应该在实践中编写这种代码。至少有两个警告信号:

  1. 你有一个包含三个以上元素的元组。这样的元组很少需要,通常可以用列表、向量或自定义数据类型替换。元组很少用于临时将两种数据合并为一个值。如果您开始经常使用元组,请考虑是否可以创建自己的数据类型。

  2. 用于read读取结构不是一个好主意。read任何微小的错误都会使您的程序爆炸,并带有可怕的错误消息,而这通常不是您想要的。如果您需要解析结构,最好使用真正的解析器。read对于简单的整数等就足够了,但仅此而已。

于 2013-10-07T11:57:41.273 回答
0

在我看来,您的困惑在于元组和列表之间。当您第一次遇到 Haskell 时,这是可以理解的混淆,因为许多其他语言只有一个类似的结构。元组使用圆括号:(1,2). 包含 n 个值的元组是一种类型,每个值可以是不同的类型,从而产生不同的元组类型。所以(Int, Int)是与 不同的类型(Int, Float),两者都是两个元组。前奏中有一些函数在两个元组上是多态的,即fst :: (a,b) -> a它采用第一个元素。fst像您自己的函数一样使用模式匹配很容易定义:

fst (a,b) = a

请注意,fst (1,2)计算结果为1,但fst (1,2,3)类型错误且无法编译。

现在,另一方面,列表可以是任意长度,包括零,并且仍然是相同的类型;但每个元素必须是同一类型。列表使用方括号:[1,2,3]. 具有 type 元素的列表的类型a被写入[a]。列表是通过将值附加到空列表来构造的[],因此可以键入具有一个元素的列表[a],但这是语法糖a:[],其中:cons运算符,它将值附加到列表的头部。就像元组可以进行模式匹配一​​样,您可以使用空列表和 cons 运算符进行模式匹配:

head :: [a] -> a
head (x:xs) = x

模式匹配的手段x是类型axs类型[a],是我们想要的前者head。(这是一个前奏功能,还有一个类似的功能tail。)

请注意,这head是一个偏函数,因为我们无法定义它在空列表的情况下的作用。在空列表上调用它会导致运行时错误,因为您可以在 GHCi 中自行检查。更安全的选择是使用 Maybe 类型。

safeHead :: [a] -> Maybe a
safeHead (x:xs) = Just x
safeHead [] = Nothing

String在 Haskell 中只是[Char]. 所以所有这些列表函数都可以用于字符串,并getLine返回一个String.

现在,在您的情况下,您需要第三个元素。有几种方法可以做到这一点,你可以调用tail几次然后调用head,或者你可以像(a:b:c:xs). 但是前奏中还有另一个效用函数,(!!)它得到了第n个元素。(编写这个函数是一个很好的初学者练习)。所以你的程序可以写成

main = do
    myString <- getLine
    print $ myString !! 2  --zero indexed

测试给出

Prelude> main
test
's'

所以请记住,元组我们()和严格具有给定长度,但可以有不同类型的成员;而列表使用'[]',可以是任意长度,但每个元素必须是相同的类型。Strings 实际上是字符列表。

编辑

顺便说一句,如果你有兴趣,我想我会提到有一种更简洁的方式来编写这个 main 函数。

main = getLine >>= print . (!!3)
于 2013-10-07T16:47:12.110 回答