自定义类型类的类型问题
Type troubles with custom typeclass
我在学习 Haskell 时遇到类型问题。
我有一个名为 Stack
的类型类,它显然应该表现得像一个堆栈。我有一个类型 Elem
,它可以是 Int 或 Bool。
现在我希望我的函数采用 Elem
的 Stack
并对其进行一些操作。结果实际上并不重要,但是我什至无法获取堆栈的第一个元素,而且我已经好几个小时都没有弄清楚出了什么问题。
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
我不太清楚你说的"not having access to the forall
syntax"是什么意思,但是如果你真的想避免它,你也可以这样写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
不过你仍然需要 ScopedTypeVariables
。
我在学习 Haskell 时遇到类型问题。
我有一个名为 Stack
的类型类,它显然应该表现得像一个堆栈。我有一个类型 Elem
,它可以是 Int 或 Bool。
现在我希望我的函数采用 Elem
的 Stack
并对其进行一些操作。结果实际上并不重要,但是我什至无法获取堆栈的第一个元素,而且我已经好几个小时都没有弄清楚出了什么问题。
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
我不太清楚你说的"not having access to the forall
syntax"是什么意思,但是如果你真的想避免它,你也可以这样写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
不过你仍然需要 ScopedTypeVariables
。