Haskell 自定义typeclass的类型问题

Haskell 自定义typeclass的类型问题,haskell,types,monads,Haskell,Types,Monads,我在学习Haskell的时候,在打字方面遇到了一些麻烦。 我有一个名为Stack的类型类,它的行为显然应该像一个堆栈。我有一个类型Elem,它只是一个Int或Bool 现在我想让我的函数获取元素的堆栈,并用它执行一些操作。结果实际上并不重要,但我甚至无法获取堆栈的第一个元素,而且我已经数小时没有找出错误所在 import Control.Monad data Elem = Number Int | Truth Bool deriving Eq instance Show Elem where

我在学习Haskell的时候,在打字方面遇到了一些麻烦。 我有一个名为
Stack
的类型类,它的行为显然应该像一个堆栈。我有一个类型
Elem
,它只是一个Int或Bool

现在我想让我的函数获取
元素的
堆栈
,并用它执行一些操作。结果实际上并不重要,但我甚至无法获取堆栈的第一个元素,而且我已经数小时没有找出错误所在

import Control.Monad

data Elem = Number Int | Truth Bool deriving Eq

instance Show Elem where
  show (Number i) = show i
  show (Truth b) = show b

class Stack stack where
  push :: a -> stack a -> stack a
  top :: MonadPlus m => stack a -> m (a,stack a)
  empty :: stack a
  isEmpty :: stack a -> Bool

instance Stack [] where
  push a stack = a:stack
  top stack = if isEmpty stack then mzero else return (head stack, tail stack)
  empty = []
  isEmpty stack = if null stack then True else False

step :: Stack stack => String -> stack Elem -> Maybe (stack Elem)
step ex st = let e1 = top st :: Maybe (Elem, stack Elem)
                 --a1 = fmap fst e1
                 --e2 = top (fmap snd e1)
                 --a2 = fmap fst e2
             in Nothing
我得到的错误是

Playground.hs:22:27:
    Could not deduce (stack ~ stack2)
    from the context (Stack stack)
      bound by the type signature for
                 step :: Stack stack => String -> stack Elem -> Maybe (stack Ele
m)
      at Playground.hs:21:9-65
      `stack' is a rigid type variable bound by
              the type signature for
                step :: Stack stack => String -> stack Elem -> Maybe (stack Elem
)
              at Playground.hs:21:9
      `stack2' is a rigid type variable bound by
               an expression type signature: Maybe (Elem, stack2 Elem)
               at Playground.hs:22:23
    Expected type: stack2 Elem
      Actual type: stack Elem
    Relevant bindings include
      st :: stack Elem
        (bound at Playground.hs:22:9)
      step :: String -> stack Elem -> Maybe (stack Elem)
        (bound at Playground.hs:22:1)
    In the first argument of `top', namely `st'
    In the expression: top st :: Maybe (Elem, stack Elem)
我真的不明白为什么Haskell拒绝这样做(甚至拒绝在我的函数中调用
top st
,而不尝试指定类型)


我希望有人能对此有所了解

正如两位评论者所建议的,您需要
-XScopedTypeVariables

以下代码为我编译:

{-# LANGUAGE ScopedTypeVariables #-}

module Foo where

import Control.Monad

data Elem = Number Int | Truth Bool deriving Eq

instance Show Elem where
  show (Number i) = show i
  show (Truth b) = show b

class Stack stack where
  push :: a -> stack a -> stack a
  top :: MonadPlus m => stack a -> m (a,stack a)
  empty :: stack a
  isEmpty :: stack a -> Bool

instance Stack [] where
  push a stack = a:stack
  top stack = if isEmpty stack then mzero else return (head stack, tail stack)
  empty = []
  isEmpty stack = if null stack then True else False

step :: forall stack . Stack stack => String -> stack Elem -> Maybe (stack Elem)
step ex st = let e1 = top st :: Maybe (Elem, stack Elem)
                 --a1 = fmap fst e1
                 --e2 = top (fmap snd e1)
                 --a2 = fmap fst e2
             in Nothing
我不确定你所说的“无法访问
所有
语法”是什么意思,但如果你真的想避免它,你也可以这样写
步骤

step :: Stack stack => String -> stack Elem -> Maybe (stack Elem)
step ex (st :: stack Elem) = let e1 = top st :: Maybe (Elem, stack Elem)
                 --a1 = fmap fst e1
                 --e2 = top (fmap snd e1)
                 --a2 = fmap fst e2
             in Nothing

您仍然需要
ScopedTypeVariables

编译器不知道
step
的类型sig中的
stack
Maybe(Elem,stack Elem)
中的
stack
相同。您正在查找
ScopedTypeVariables
,但这意味着您必须将sig更改为
step::forall stack。Stack Stack=>String->Stack Elem->Maybe(Stack Elem)
@bheklillr我无权访问forall语法。一定有可能在我的函数中得到堆栈的第一个元素?!您是否将
{-#语言范围的TypeVariables}
放在文件的顶部?