Ambiguous occurrence in Haskell with “show”

前端 未结 1 1506
花落未央
花落未央 2021-01-25 04:02

I\'m new in functional programming and I\'m trying to create and show a Stack with Haskell. I\'d like my program to show me the Stack I\'m building with it. This is my code:

相关标签:
1条回答
  • 2021-01-25 04:30

    So the first problem is that you've got a ` character in the code you pasted for us. Your second problem is that you don't need to indent all of the lines in the module; most Haskell modules that I see will not indent the body of the module. Your third problem is that you do not need parentheses around show a and show b: precedence in Haskell is really simple; parentheses always take top priority, followed by function application (left-associative or "greedy nom", a function always gobbles up the first thing that it sees in front of it), followed by operators in their defined precedence, followed by special syntactic forms like \a ->, let, do, where. Those are generally aesthetic concerns but you probably still care.

    Your final problem is here:

    instance Show a => Show (Stack a) where
    show EmptyStack = "|"
    show (Stk a b) = (show a) ++ " <- " ++ (show b)
    

    You want Haskell to turn this into the single statement:

    instance Show a => Show (Stack a) where show tmpvar = case tmpvar of { EmptyStack -> "|"; Stk a b -> show a ++ " <- " ++ show b }
    

    However Haskell has instead turned this into two separate lines:

    instance Show a => Show (Stack a) where {} 
    
    show tmpvar = case tmpvar of { EmptyStack -> "|"; Stk a b -> show a ++ " <- " ++ show b }
    

    So the multiple-definition is correctly converted into a case-dispatch, but it's not put within the curly braces above! So, you can omit curly braces {} by using whitespace to indent lines. After where, Haskell does not see any explicit {} so it starts looking for indented lines, and it sees 0 of them, so it converts the clause to where {} (thanks @chi).

    Without being in curly braces, either because of indentation or not, that new line defines a different function, Stack.show, distinct from the imported Prelude.show that belongs to the Show typeclass. The problem is that it also references a function called show, which is now ambiguous: is this a recursive call for a function with infinite type show :: Stack (Stack (Stack ...)) -> String or a dispatching call for a function with finite type show :: (Show a) => Stack a -> String? Before it even tries to figure out those types it says "stop it, I don't know what you mean, please clarify."

    Probably what you intended was instead:

    instance Show a => Show (Stack a) where
        show EmptyStack = "|"
        show (Stk a b) = show a ++ " <- " ++ show b
    

    This indentation clues the Haskell compiler to accepti the two following statements into the where clause.

    0 讨论(0)
提交回复
热议问题