import qualified Prelude
class List list where
toList :: list a -> [a]
fromList :: [a] -> list a
data Deque a = Deque [a] [a]
instance List Deque where
toList (Deque xs sy) = xs reverse sy
fromList xs = Deque ys (reverse zs)
where (ys, zs) = splitAt (length xs `div` 2) xs
我收到一个错误,如下所示。GHCI 似乎没有检测ys
为 Deque,而是作为 List 类的一般实体。
ghci> xs = [2, 3, 4]
ghci> ys = fromList xs
ghci> (Deque a b) = ys
ghci> toList (Deque a b)
[2,3,4]
ghci> toList ys
<interactive>:5:1: error:
* Could not deduce (List list0) arising from a use of `toList'
from the context: Num a
bound by the inferred type of it :: Num a => [a]
at <interactive>:5:1-9
The type variable `list0' is ambiguous
These potential instance exist:
instance [safe] List Deque -- Defined at main.hs:12:10
* In the expression: toList ys
In an equation for `it': it = toList ys
uj5u.com热心网友回复:
ghci> let xs = [2, 3, 4]
ghci> let ys = fromList ys
此时,这些值可能具有最通用的类??型:
ghci> :t xs
xs :: Num a => [a]
ghci> :t ys
ys :: (List list, Num a) => list a
没有暗示 a Deque
,这是有道理的,因为您还没有提到任何双端队列。
但是这些变量保持不变,它们不会改变它们的型别!
所以之后
ghci> (Deque a b) = ys
ghci> toList (Deque a b)
[2,3,4]
你仍然有同样的情况ys
,即
ghci> :t ys
ys :: (List list, Num a) => list a
当然,您曾经用作ys
双端队列,这是可以使用的一种方式。但由于是多型的,它也可以是任何其他List
型别,GHCi 不会做出任何猜测它应该是什么。但你当然可以告诉它:
ghci> toList (ys :: Deque Int)
[2,3,4]
或者更短
ghci> :set -XTypeApplications
ghci> toList @Deque ys
[2,3,4]
uj5u.com热心网友回复:
这是按设计作业的。当你写:
λ> ys = fromList xs
分配给的型别ys
是:
λ> :t ys
ys :: (List list, Prelude.Num a) => list a
也就是说,ys
是一个多型值,可以“是”任何型别的List
.
因此,当您将其系结到特定模式时:
λ> Deque a b = ys
thenys
被实体化为 aDeque
并且适当的值系结到a
and b
,但这不会使ys
单态。也就是说,ys
还没有突然“变成”一个Deque
. 相反,它仍然是一个多型值,可以反弹到其他一些List
. 例如,如果您还有一个普通旧串列的实体:
instance List [] where
toList = id
fromList = id
您可以实体化ys
多种型别:
λ> xs = [2, 3, 4]
λ> ys = fromList xs
λ> Deque a b = ys -- instantiate as Deque
λ> c:d = ys -- instantiate as []
如果这让您感到奇怪,请考虑:
λ> id "hello"
λ> id 'x'
两者都有效,即使第一次使用多型值id :: a -> a
,它也被实体化为String -> String
,而第二次使用时,它被实体化为Char -> Char
. 这是相同的原理。
0 评论