在这里完成nok到haskell,我正在努力使这段代码工作:
它的目的是获取列表的第一个exp元素,连接它们,然后再次调用相同的函数。
order ( i ) (l1)(l2) =
do exp <- (2 ^ i)
l <- (take exp l1) ++ (take exp l2 ) ++ (order (i+1) (drop exp l1) (drop exp l2));
return l
我确信这远不是惯用的哈斯克尔,但你必须在某处开始。
我得到的错误是
exp <- (2 ^ i )
说
No instance for (Num [Int])
arising from a use of `^'
Possible fix: add an instance declaration for (Num [Int])
我真的不确定这究竟意味着什么。是不是2和i都是整数,然后应用指数函数会产生整数?
谢谢!
答案 0 :(得分:5)
我已按如下方式重写您的代码,并添加了一个主要内容。
order _ [] [] = []
order i l1 l2 =
(take exp l1) ++ (take exp l2)
++ (order (i+1) (drop exp l1) (drop exp l2))
where
exp = 2^i
main = print $ order 1 [1,2,3,4] [3,4,5,6]
你犯的第一个错误就是你的递归没有终止,因为order
总会再次自我调用。第二个错误是使用do
,这引入了monad
并且考虑到你是Haskell的新手,我会保持清醒一点。目前仅用于I / O.
我希望这会有所帮助。
P.S:您收到的错误消息是,Int
列表以数字方式使用,并且没有默认实现。这可能是由monad列出的do
引起的,但是我会把它留在Haskell的裂缝中给出一个确切的解释。
答案 1 :(得分:3)
do
块中的所有语句必须属于同一个monad。这包括<-
绑定的右侧。因此,因为第二个语句take exp l1 ++ ...
的右侧是一个列表,编译器会推断2^i
的类型也必须是一个列表。
这是因为<-
不只是分配变量。在列表monad的情况下,它顺序地将左侧的变量绑定到右侧列表的每个元素。
如果您只想在do
块中绑定变量而不产生任何其他影响,则应使用let
绑定而不是<-
。
do let exp = 2^i
l <- take exp l1 ++ ...
return l
尽管如此,在这里使用do
符号是多余的。 monad法律保证do x <- m; return x
与m
相同,因此您可以直接将其写为
order i l1 l2 = take exp l1 ++ ...
where exp = 2^i
答案 2 :(得分:2)
除了布莱恩的观点,我想我可以帮助解释你遇到这个特定错误的原因。
最重要的原因是exp <- 2 ^ i
块中的do
确实不意味着“让exp
成为2 ^ i
值的名称“(你会在do块中将这个含义表示为let exp = 2 ^ i
,但是do
块实际上并不是你想要的那样。”
exp <- 2 ^ i
的含义是“let exp
是monadic值2 ^ i
”产生的值的名称。尝试阅读<-
,因为“来自”而不是“是”。究竟“来自”意味着什么取决于所涉及的单子。因此,对于这一行来说,2 ^ i
必须是某种monad中的值。具体来说,它的类型类似Monad m => m a
,适用于未知m
和a
。
由于^
运算符适用于数值,因此会返回Num a => a
类型的内容。因此,我们可以确定2 ^ i
应该是类型为(Monad m, Num (m a)) => m a
的内容,适用于未知m
和a
。
exp
是从这个神秘的m a
中提取出来的,所以它的类型为a
。下一行包含take exp l1
等表达式。 take
要求其第一个参数属于Int
类型,因此exp
必须是Int
类型,因此我们可以告诉那个未知的a
我们与...合作必须Int
。因此,2 ^ i
现在已知为(Monad m, Num (m Int)) => m Int
类型;它是某种一元整数。
在这一行中,您还有l <- (take exp l1) ++ ...
。所以l
也“来自”某种一元的价值。右侧可以看作是某种列表(由于使用了++
,take
和drop
)。参与do
块的monad必须始终相同,并且列表类型构造函数确实是monad。因此,如果(take exp l1) ++ ...
是某个列表,那么2 ^ i
也必须是某个列表。
现在我们2 ^ i
属于[Int]
类型(我们原先知道它是m a
; m
是列表类型构造函数[]
,并且a
是Int
)。但我们也知道(使用^
运算符)它必须是Num
类型类的成员。 <{1}}没有Num
的实例,这正是你得到的错误。
这只是可以从您编写的代码中获得的许多不一致之一;这只是GHC在尝试分析时遇到的第一个。