Mapping type A & # 8594; A

data A = Num Int | Fun (A -> A) String deriving Show instance Show (Fun (A -> A) String) where show (Fun fs) = s 

I would like to have an attribute for the function A -> A to print it, so the String parameter is of type Fun . When I upload this to ghci, I get

 /home/kmels/tmp/show-abs.hs:4:16: Not in scope: type constructor or class `Fun' 

I guess this can be achieved by adding a new data type

 data FunWithAttribute = FA (A -> A) String 

adding data A = Num Int | Fun FunWithAttribute data A = Num Int | Fun FunWithAttribute and instance Show FunWithAttribute record instance Show FunWithAttribute . Is it possible to avoid using an additional data type?

+6
source share
3 answers

Instances are defined for types in general, and not for individual constructors, so he complains that Fun not a type.

I assume that your common goal is to have a Show instance for A that cannot be inferred because functions cannot (in general) have a Show instance. You have a couple of options:

Write your own instance of Show :

That is, something like:

 instance Show A where show (Num n) = "Num " ++ show n show (Fun _ s) = s 

In many cases, this makes the most sense. But sometimes it is better to retrieve Show , especially in complex recursive types, where only one case of many is not automatically Show -able.

Print A output:

You can only get Show for types containing types that have instances of Show . There is no instance for A -> A , so the output does not work. But you can write one that uses some kind of placeholder:

 instance Show (A -> A) where show _ = "(A -> A)" 

Or even an empty string if you want.

Note that this requires an extension of the FlexibleInstances language ; it is one of the safest and most commonly used extensions, supported by several Haskell implementations, and the restrictions that it relaxes are, in my opinion, a little silly to start with, so there is no reason to eliminate it.

An alternative approach would be to have a type of wrapper, as you mentioned in the question. You can even make it more general:

 data ShowAs a = ShowAs a String instance Show (ShowAs a) where show (ShowAs _ s) = s 

... and then use (ShowAs (A -> A)) in the Fun constructor. This makes it a little inconvenient, forcing you to make an additional template, matching any time you want to use a wrapped type, but it gives you more flexibility to “mark” the material with how it should be displayed, for example. showId = id `ShowAs` "id" or the like.

+11
source

Perhaps I am not following what you are asking. But the above code can be written to compile:

 data A = Num Int | Fun (A -> A) String instance Show A where show (Fun fs) = s show (Num i) = show i 

Some explanation

It looks like you were trying to write a show instance for the constructor (Fun). Instance instances are written for the entire data type (there may be exceptions, dunno). Therefore, you need to write one show match for each constructor as part of the instance. Num and Fun are each data type A constructor.

In addition, deriving cannot be used if each parameter of each constructor, in turn, is not a member of Show in this case. Now your example is a bit special, as it wants Show (A -> A) . How to show the function is somewhat explained in other answers, although I don't think there is an exhaustive way. Other examples really just “show” the type or place of the owner.

+5
source

A Show instance (or any class instance) should be defined for the data type, not for the type constructor. That is, you just need to

 instance Show A where 

Apparently you are trying to get this instance with deriving , but this does not work because Haskell does not know how to show A->A Now it seems that you don’t even want to show this function, but the deriving Show instances always show all the available information, so you cannot use it.

The obvious and best solution to your problem is mirrors: don’t use deriving at all, but determine the correct instance yourself. Alternatively, you can define a pseudo instance for A->A , and then use the output:

 {-# LANGUAGE FlexibleInstances #-} data A = Num Int | Fun (A->A) String deriving(Show) instance Show (A->A) where show _ = "" 

It works like

 Prelude> Fun (const $ Num 3) "bla" Fun "bla" 
+4
source

All Articles