2015-01-15 2 views
1

하스켈을 배우는 동안 유형에 문제가 있습니다. 분명히 스택처럼 동작해야하는 Stack이라는 typeclass가 있습니다. 나는 타입이 Elem이며 Int 나 Bool 중 하나 다.사용자 정의 typeclass 유형 문제

이제 StackElem으로 가져와 일부 기능을 사용하고 싶습니다. 결과는 실제로 중요하지 않지만 스택의 첫 번째 요소를 얻지 못하고 몇 시간 동안 무엇이 잘못되었는지 파악하지 못했습니다.

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 

내가 점점 오전 오류가 하스켈이를 거부 (심지어 나를 유형을 지정하려고하지 않고 단순히 내 기능에 top st를 호출 거부) 왜 내가 정말보고 실패

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) 

입니다.

나는 누군가가 이것에 대해 밝힐 수 있기를 바랍니다.

+4

컴파일러는'step'의 sig 형식의'stack'이'Maybe (Elem, stack Elem) '의'stack'과 같은지 알지 못합니다. 당신은'ScopedTypeVariables'를 찾고 있지만, 그것은 sig를'step :: forall stack '으로 바꾸어야한다는 것을 의미합니다. 스택 스택 => 문자열 -> 스택 엘레 -> 어쩌면 (스택 엘름)'. – bheklilr

+0

@bheklilr forall 구문에 액세스 할 수 없습니다. 어떻게 든 내 함수에서 스택의 첫 번째 요소를 얻을 수 있어야합니다! – Marco

+3

'{- # LANGUAGE ScopedTypeVariables # -}'를 파일 상단에 넣었습니까? – bheklilr

답변

1

두 명의 의견 제시자가 제시 한대로 -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 

당신 "이 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 

당신은 여전히하지만 ScopedTypeVariables 필요합니다.

관련 문제