简体   繁体   English

自定义类型类的类型麻烦

[英]Type troubles with custom typeclass

I'm having some trouble with types while learning Haskell. 我在学习Haskell时遇到类型问题。 I have a typeclass called Stack which obviously should behave like a stack. 我有一个称为Stack的类型类,显然应该表现得像一个堆栈。 I have a type Elem which is simply either an Int or a Bool. 我有一个Elem类型,它只是一个Int或Bool。

Now I want my function to take a Stack of Elem and do some operations with it. 现在,我想我的功能采取StackElem ,并做一些操作它。 The result is not actually important, however I am failing to even acquire the first element of the stack and I have failed to figure out what is wrong for hours now. 结果实际上并不重要,但是我什至没有获得堆栈的第一个元素,而且现在几个小时都没弄清什么地方出了问题。

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

The error I am getting is 我得到的错误是

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)

I really fail to see why Haskell refuses this (and even refuses simply calling top st in my function without me trying to specify a type). 我真的不明白为什么Haskell会拒绝此操作(甚至拒绝在我不尝试指定类型的情况下在函数中直接调用top st )。

I hope someone can shed some light on this! 我希望有人能对此有所启发!

As two commenters suggested, you need -XScopedTypeVariables . 正如两个评论者所建议的那样,您需要-XScopedTypeVariables

The following code compiles for me: 以下代码为我编译:

{-# 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

I'm not sure what you mean about "not having access to the forall syntax", but if you really want to avoid it, you can also write step like this: 我不确定“无法访问forall语法”的含义,但是如果您真的想避免这种情况,也可以编写如下step

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

You'll still need ScopedTypeVariables though. 但是,您仍然需要ScopedTypeVariables

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM