我想将转换列表[[1,2,3],[2,3]]转换为元组[(1,2,3),(2,3)]
我的职能:
thr [a,b,c] = (a,b,c)
tupel [] = []
tupel (x:xs) = if length x==3 then thr x:(tupel xs) else (tupel xs)
这项工作有三个要素。
thr [a,b,c] = (a,b,c)
two [a,b] = (a,b)
tupel [] = []
tupel (x:xs) = if length x==3 then thr x:(tupel xs) else two x:(tupel xs)
为什么不这样做?
错误:在应用程序中键入错误 *表达式:两个x:tupel2 xs 术语:两个x 类型:(a,a) * 不符合:(a,a,a)
答案 0 :(得分:6)
好的,让我们跳到最后并启动ghci。 [(1,2,3),(1,2)]
有哪些类型?
ghci> :t [(1,2,3),(1,2)]
<interactive>:1:10:
Couldn't match expected type `(t0, t1, t2)'
with actual type `(t3, t4)'
In the expression: (1, 2)
In the expression: [(1, 2, 3), (1, 2)]
In an equation for `it': it = [(1, 2, 3), (1, 2)]
该错误不是因为我输入数据错误,而是因为[(1,2,3),(1,2)]
无效haskell。
haskell中的列表可以包含无限数量的项目,但需要注意的是所有项目必须属于同一类型。
这可能看起来很奇怪,但(1,2,3)
和(1,2)
的类型不同。一个是3元组,一个是2元组。
元组与列表相反 - 它只能容纳特定数量的项目,但它们可以是一堆不同的类型。元组类型由它们包含的项目给出的类型序列定义。
因此,3个整数的元组(或者,如ghc将显示的,类似数字的东西)与2个整数的元组不同。我们可以使用ghci中的:t
运算符直接看到这一点:
ghci> :t (1,2,3)
(1,2,3) :: (Num t1, Num t2, Num t) => (t, t1, t2)
ghci> :t (1,2)
(1,2) :: (Num t1, Num t) => (t, t1)
请注意(2,3,4)
和(2,3)
的类型分别与(1,2,3)
和(1,2)
匹配:
ghci> :t (2,3,4)
(2,3,4) :: (Num t1, Num t2, Num t) => (t, t1, t2)
ghci> :t (2,3)
(2,3) :: (Num t1, Num t) => (t, t1)
这是因为(2,3,4)
和(1,2,3)
是两个具有相同类型的值。 (1,2)
和(2,3)
也是如此。
因此,在haskell中没有将[[1,2,3],[1,2]]
转换为[(1,2,3),(1,2)]
的函数,因为这样的函数的结果无法进行类型检查。
答案 1 :(得分:4)
元组有不同的类型,因此没有单一(简单)类型可以提供给tupel
函数。
但是,通过退回并使用 sum类型,您可以对要返回的所有变体进行编码:
data T a
= One a
| Two a a
| Three a a a
deriving Show
two :: [a] -> T a
two [a,b] = Two a b
thr :: [a] -> T a
thr [a,b,c] = Three a b c
tuple :: [[a]] -> [T a]
tuple [] = []
tuple ([a,b] :xs) = Two a b : tuple xs
tuple ([a,b,c]:xs) = Three a b c : tuple xs
tuple (_ : xs) = tuple xs
注意我们如何通过模式匹配来区分两元素和三元素列表。
其次,优良作法是记下每个函数的预期类型 - 这将有助于解决设计中的混淆,并快速揭示逻辑错误,如两种不同的元组类型。
运行它,你可以看到它如何很好地分组:
*Main> tuple [[1,2,3],[2,3]]
[Three 1 2 3,Two 2 3]