我正在尝试在运行时连接函数(必须这样做),这可能涉及函数输入和输出中的类型类约束,这让我很苦恼。
在像Java这样的语言中,这很简单。例如
类型类允许您避免在数据类型之间进行转换。我们可以随意地来回转换并摆脱类型类。但问题是我们无缘无故地创建了大量的对象。让我们尽量避免这种情况。
我开始尝试创建一个元组(a, Api a),其中Api是对将对a操作的函数进行记录的记录。我猜这与类型类的工作方式非常相似?但然后你会遇到具体类型问题,我想到了存在性。但是然后我意识到(a, Api a)应该能够完全隐藏a,因为没有人关心它,然后Api变成了纯数据类型记录,而不是函数。
所以我不得不想知道……是懒惰解决了这个问题吗?
在像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 值,因为我们只需要调用 MyData 值上的 myf2 函数?
所以,“等同于” Java 接口的东西并不是类型类,而是记录或数据类型?惰性提供了接口的“轻量级”特性?