Собственные типы данных - Преобразование между ними и собственными

Мне нужно сделать свой собственный тип данных для представления натуральных чисел. Типы данных (предварительно) определены, как показано ниже. Кроме того, мне нужно создать функции для преобразования между собственным типом данных Int и заданным. Мне удалось преобразовать из Int в заданные, а также проверить, является ли мой тип данных ZZ нулевым. Хотя я действительно не могу найти способ преобразовать что-либо, кроме нуля, обратно в Int. Я надеюсь, что вы, ребята, можете дать мне подсказку о том, как это сделать.

data IN_1 = One | Follower IN_1 deriving Show
data ZZ   = Zero | Plus IN_1 | Minus IN_1 deriving Show

type Zed = Int


from_Zed_to_ZZ :: Zed-> ZZ
from_Zed_to_ZZ x 
 | x == 0 = Zero
 | x > 0 = Plus (helper(x))
 | x < 0 = Minus (helper(abs(x)))

helper :: Zed -> IN_1
helper x 
 | x==1 = One
 | otherwise = Follower (helper(x-1))


instance Eq ZZ where
    (==) Zero Zero = True


from_ZZ_to_Zed :: ZZ -> Zed
from_ZZ_to_Zed x |x == Zero = 0

Это мои текущие тестовые случаи: тестовые случаи


person Florian Drucker    schedule 24.10.2019    source источник
comment
Вы можете использовать сопоставление с образцом, поэтому from_ZZ_to_Zed (Plus x) = ...   -  person Willem Van Onsem    schedule 24.10.2019
comment
Думаю, это все, что мне было нужно. Спасибо, сэр!   -  person Florian Drucker    schedule 24.10.2019


Ответы (1)


Способ «развернуть» значения, заключенные в алгебраические типы данных, заключается в сопоставлении с образцом. Каждый параметр функции — это не просто идентификатор, а настоящий шаблон. Образец может быть просто идентификатором, но может быть и другим. В частности, шаблон может быть указан как имя конструктора данных (например, Plus), за которым следует один или несколько других шаблонов, по одному для каждого параметра этого конструктора.

В твоем случае:

from_ZZ_to_Zed :: ZZ -> Zed
from_ZZ_to_Zed Zero = 0
from_ZZ_to_Zed (Plus x) = ...
from_ZZ_to_Zed (Minus x) = ...

Затем, чтобы преобразовать из IN_1 в Zed, используйте рекурсию, аналогичную тому, как вы реализовали helper:

unhelper :: IN_1 -> Zed
unhelper One = 1
unhelper (Follower x) = unhelper x + 1

И используйте это для случаев Plus и Minus:

from_ZZ_to_Zed (Plus x) = unhelper x
from_ZZ_to_Zed (Minus x) = - (unhelper x)
person Fyodor Soikin    schedule 24.10.2019
comment
Я сам догадался, что Виллем Ван Осем наставил меня на верный путь! Спасибо за помощь! :) - person Florian Drucker; 24.10.2019