我试图解决the 99 problems in Haskell,而对于第4个问题,我首先尝试了这样的解决方案
myLength :: [a] -> Int
myLength [] = 0
myLength ys = go 1 ys
where
go :: Int -> [a] -> Int
go n xs
| ( (take n xs) == (take (n+1) xs) ) = n
| otherwise = go (n+1) xs
但是,编译器会给出错误:
Problem4.hs:10:8: error:
• No instance for (Eq a1) arising from a use of ‘==’
Possible fix:
add (Eq a1) to the context of
the type signature for:
go :: forall a1. Int -> [a1] -> Int
• In the expression: ((take n xs) == (take (n + 1) xs))
In a stmt of a pattern guard for
an equation for ‘go’:
((take n xs) == (take (n + 1) xs))
In an equation for ‘go’:
go n xs
| ((take n xs) == (take (n + 1) xs)) = n
| otherwise = go (n + 1) xs
|
10 | | ( (take n xs) == (take (n+1) xs) ) = n
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
据我所知,错误的原因是当我们尝试比较从(take n xs)
和(take (n+1) xs)
返回的列表时,编译器事先并不知道列表的类型,所以它无法比较它们,这就是为什么它会抱怨,所以在这一行之前,我需要告诉编译器两个返回值是相同的类型,类型是[a]
,但我们怎么能这样做呢? / p>
混淆:当我们指定go
的类型签名时,我们明确地修复了xs
的类型,即不应该这样做函数take
返回的列表具有相同的类型,即[a]
,因此编译器是否应该能够比较它们?
修改
请注意,我在函数的定义中有另一个函数,并且有很多东西与标记为重复的问题不同,正如您所观察到的,对该问题的给定答案并不完全解决了这个问题。
答案 0 :(得分:2)
您需要的是实例上下文(此处为Eq a
),由=>
表示:
myLength :: Eq a => [a] -> Int
myLength [] = 0
myLength ys = go 1 ys
where
go :: Eq a => Int -> [a] -> Int
go n xs
| ( (take n xs) == (take (n+1) xs) ) = n
| otherwise = go (n+1) xs
但这不是问题#4的正确答案,因为它为函数添加了额外的约束。
编辑:对于问题“不应该每个列表都具有可比性吗?”:
如果列表的元素具有可比性,则列表具有可比性。例如,函数Kleisli
箭头,WrappedArrow
s不具有可比性,因此不是它们的列表。
答案 1 :(得分:1)
{-# Language ScopedTypeVariables #-}
myLength :: forall a. Eq a => [a] -> Int
myLength [] = 0
myLength ys = go 1 ys
where
go :: Int -> [a] -> Int
go n xs
| take n xs == take (n+1) xs = n
| otherwise = go (n+1) xs