У меня ужасные времена, когда я пытаюсь подключить функции во время выполнения (что мне и приходится делать), которые могут включать ограничения класса типов во входных и выходных данных функции.
На таком языке, как Java, это было бы тривиально. f1 :: Int -> Num
, f2 :: Num -> Num
Теперь мы можем вызвать f2. f1
. Если бы Num был интерфейсом в стиле Java, это не сработало бы. Но классы типов не ведут себя как интерфейсы.
Классы типов позволяют избежать преобразования между типами данных. Мы могли бы просто преобразовать туда и обратно и избавиться от классов типов. Но проблема в том, что мы создаем объекты повсюду без причины. Попробуем этого избежать.
Я начал с попытки создать кортеж из (a, Api a), где Api - это запись функций, которые будут работать с a. Я предполагаю, что это, вероятно, очень похоже на то, как работают классы типов? Но затем вы сталкиваетесь с проблемой конкретного типа, и я подумал о существовании. Но затем я понял, что (a, Api a) должен иметь возможность полностью скрыть a, поскольку никого не волнует, и тогда Api превращается в простую запись типов данных, а не функций.
И поэтому мне остается только гадать ...Разве это решает лень?
module Main where
--data Api a = Api { f1 :: a -> Int, f2 :: a -> String }
data Api = Api { f1 :: Int, f2 :: String }
data MyData = MyData Int String
myf1 (MyData x y) = x
myf2 (MyData x y) = y
myApi x = Api (myf1 x) (myf2 x)
from :: Int -> Api
from x = myApi $ MyData x "string"
to :: Api -> String
to api = f2 api
main = print $ to . from $ 5
Итак, достаточно ли у него ума (или могло бы быть), чтобы понять, что ему вообще не нужно создавать значение Api, поскольку все, что нам нужно, - это вызов myf2 для значения MyData?
Значит, «эквивалент» интерфейса Java - это не класс типа, как мне однажды сказали, а скорее запись или тип данных? И эта лень обеспечивает «легковесность» интерфейса?