Using data types in Haskell

I started this new question as it was a continuation of my previous question.

If I have two data types that consist of similar constructors:

data A = X | Y | Z data B = X | Y 

I cannot somehow imagine this as:

 data A = C | Z data B = C data C = X | Y 

if you can see what I'm doing - I'm trying to group X | Y into one data type, which can then be used by several other data types. I can not get the compiler to allow this, or if it is, I can not match the pattern with X or Y, only C ??

I get an error that C has been declared several times.

I thought I could use types, but they do not allow multiple vices.

EDIT

Even if I declare a long path (e.g. below), it still will not compile and says that X and Y have several declarations:

 data A = X | Y | Z data B = X | Y 
+6
source share
4 answers

Not only can you not do this, but you can’t do your first option - that is, you cannot have two types in one module that have constructors named X and Y

If you could do this, what should the X be type be - C , A or B ? The most obvious answer would be C , but then you cannot use it in a context where A or B required (note that Haskell has no subtypes), so this will defeat the purpose of the whole construct.

The best thing you can do is wrap C in constructor A and B, i.e.:

 data A = AC C | Z data B = BC C data C = X | Y 

You can then wrap C with the AC or BC constructor to create a value of type A or B respectively.

+13
source

The reason you cannot do this

 data A = X | Y | Z data B = X | Y 

as follows. Say you write the code later:

 foo n = (n,X) 

which builds a pair consisting of n in the first slot and X in the second slot. What type should the compiler output? The valid type is

 foo :: a -> A -> (a,A) 

since X is a constructor of type A , but equally true

 foo :: a -> B -> (a,B) 

since X is a constructor of type B If you have two constructors with the same name, you cannot deduce a unique type for functions that use them. Thus, you are not allowed to specify two constructors in the same module with the same name.

+4
source

You cannot do this:

 data A = C | Z data B = C data C = X | Y 

(Aside, if B matches C , then why B at all?)

But you can do something like this:

 data A = A_Other C | Z data B = B_Other C data C = X | Y 

Then you can map the pattern as follows:

 foo :: A -> String foo (A_Other X) = "X" foo (A_Other Y) = "Y" foo ( Z) = "Z" bar :: B -> String bar (B_Other X) = "X" bar (B_Other Y) = "Y" foobar :: C -> String foobar X = "X" foobar Y = "Y" 

If that makes sense ...

+1
source

You cannot do what you want because you declare multiple data constructors. IN

 data A = X | Y | Z 

In fact, you type A , which has 3 constructors (values) X , Y and Z That's why your first code fragment will not compile, it sees the same name as the constructors for two different types! If you could do this, you need to ask yourself:

 X :: A 

or

 X :: B 

which in an object oriented context is scary! Therefore, you need to provide different constructor names for sharing this basic data, C

If you want to influence this, you can do the same as other messages that suggested and considered data in unique constructors for each data type

 data A = CForA C | Z data B = CForB C data C = X | Y 
0
source

Source: https://habr.com/ru/post/924973/


All Articles