Yes, I checked the example you sent. Great one.
It may be even smart to implement __add__ in your original example, because this way you can alter ConcatDataset type when you print the type.
d1= DataLoader(x + y, batch_size=1)
print(d1.dataset)
print(type(d1.dataset)) #ConcatDataset type
import torch
import numpy as np
from torch.utils.data import Dataset, DataLoader
import torch.utils.data as data_utils

class NpDataset(Dataset):
  def __init__(self, array):
    self.array = array
  def __len__(self): return len(self.array)
  def __add__(self, ds): 
        return data_utils.TensorDataset(  torch.from_numpy(self.array + ds))
        
        
        
  def __getitem__(self, i): return self.array[i]

x = np.arange(3)
print(x)
y = np.arange(3, 6)
print(y)

data_x = NpDataset(x)
data_y = NpDataset(y)

d1 =DataLoader(x + y, batch_size=1)
    
print("...")
d2 = DataLoader(data_x + data_y, batch_size=1)

print(d1.dataset)    
print(d2.dataset)

outputs
[0 1 2]
[3 4 5]
...
[3 5 7]
<torch.utils.data.dataset.TensorDataset object at 0x000001ABF4C8F208>

I am not sure what is the best practice.
Should we have our DataLoader. dataset as Tensor or np array, or TensorDataset, or ContactDataset.
I assume ContactDataset is very good as I can do d2.dataset.datasets, and list all the `NpDataset`s inside.
But why this may be useful?