Haskell:类型变量对于类实例不明确

Fre*_*y J 1 haskell types class

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
Run Code Online (Sandbox Code Playgroud)

我收到如下复制的错误。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
Run Code Online (Sandbox Code Playgroud)

lef*_*out 6

ghci> let xs = [2, 3, 4]
ghci> let ys = fromList ys
Run Code Online (Sandbox Code Playgroud)

此时,这些值可能具有最通用的类​​型:

ghci> :t xs
xs :: Num a => [a]
ghci> :t ys
ys :: (List list, Num a) => list a
Run Code Online (Sandbox Code Playgroud)

没有任何 a 的暗示Deque,这是有道理的,因为您还没有提到任何双端队列。

但这些变量保持不变,并且不会改变其类型!

所以之后

ghci> (Deque a b) = ys
ghci> toList (Deque a b)
[2,3,4]
Run Code Online (Sandbox Code Playgroud)

你仍然有同样的情况ys,即

ghci> :t ys
ys :: (List list, Num a) => list a
Run Code Online (Sandbox Code Playgroud)

当然,您曾经用作ys双端队列,这是它的一种使用方式。但由于它是多态的,它也可以是任何其他List类型,并且 GHCi 不会对其应该是什么进行任何猜测。但你当然可以直接告诉它

ghci> toList (ys :: Deque Int)
[2,3,4]
Run Code Online (Sandbox Code Playgroud)

或者更短

ghci> :set -XTypeApplications 
ghci> toList @Deque ys
[2,3,4]
Run Code Online (Sandbox Code Playgroud)