我正在试图解决Haskell的99个问题,对于第四个问题,我首先尝试了这样一个解决方案
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]
,但是我们如何做到这一点呢?
A混淆:当我们指定go
的类型签名时,我们显式地修正了xs
的类型,也就是说,函数take
返回的列表不应该具有相同的类型,即[a]
,因此编译器难道不能比较它们吗?
编辑:
请注意,我在函数的定义中有另一个函数,并且有许多与标记为重复的问题不同的地方,正如您所观察到的,给出的问题的答案并不能完全解决这个问题。
发布于 2018-03-10 12:30:55
您需要的是实例上下文(此处为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
不相等,它们的列表也是不可比拟的。
发布于 2018-03-10 12:47:11
{-# 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
https://stackoverflow.com/questions/49209012
复制相似问题