Haskell 从B或其他有用的东西
我有:Haskell 从B或其他有用的东西,haskell,Haskell,我有: 我想编写函数::ca=>a,它将创建dsomestring。我将调用anyC并获取a,即AnyD。下一步是从AnyD创建dsomestring。在大多数现代语言中,这很容易。对于Haskell,我在Constrb中找到并看到了。所以,这个目标似乎是可行的,但是。。我遇到了一个问题,这篇文章看起来是错误的:我不能以Chris的方式构造任何东西,因为构造函数参数必须是代数类型,并且类似于fromcontr(toConstr(1::Int))的代码返回错误异常:Data.Data.constr
我想编写函数
::ca=>a
,它将创建dsomestring
。我将调用anyC
并获取a
,即AnyD
。下一步是从AnyD
创建dsomestring
。在大多数现代语言中,这很容易。对于Haskell,我在Constrb中找到并看到了。所以,这个目标似乎是可行的,但是。。我遇到了一个问题,这篇文章看起来是错误的:我不能以Chris的方式构造任何东西,因为构造函数参数必须是代数类型,并且类似于fromcontr(toConstr(1::Int))
的代码返回错误异常:Data.Data.constrIndex不支持Prelude.Int,因为它不是代数数据类型。
。这同样适用于String
,因此我无法将我的someString
传递给我的构造函数!如何解决这个问题 具有类型的定义
class C a where
anyC :: a
data D = D String|AnyD deriving (Eq, Show, Data)
instance C D where
anyC = AnyD
承诺提供任何类型的值a
,只要它在类C
内。foo
的用户可以选择a
,foo
本身无法选择特定类型
使用您的设置,唯一可能的(非错误)定义是
foo :: C a => a
如果要返回D“hello”
,则这是D
类型。如果需要,可以使用该类型:
foo = anyC
还请注意,如果需要,还可以更改实例:
bar :: D
bar = D "hello"
关于
在大多数现代语言中,这很容易
事实并非如此。例如,在Java中,一个模糊的等价物可以是
//类型类,大致如下
接口C{
A anyC();
}
类D实现C{…}
阿福(){
返回新的D(…);
}
Java也不会接受这一点。除了其他问题,foo()
承诺返回调用者选择的任何A
,但它不能选择返回D
Haskell类型变量大致对应于Java的泛型类型参数。您可能会转而考虑子类型,它存在于Java和其他OOP语言中,但Haskell没有使用
如果您想要一个来自constrb的示例,您可以尝试以下方法:
instance C D where
anyC = D "hello"
foo
计算结果为D“新字符串”
。这可以通过嵌套case eqT
s进行扩展,以便field
覆盖更多类型(如果构造函数需要更多类型),以便我们检查所有需要的类型
还要注意,fromConstrB的是有限的,因为如果我们的构造函数有两个相同类型的字段,我们就不能用不同的值填充字段。为此,我认为,我们需要从constrm
中求助于更复杂的
这里有一个小的方便助手函数。它接受一个Constr
,以及一个“非类型化”参数列表(Dynamic
在运行时进行所有类型检查),并尝试构建一个将构造函数应用于给定参数的值
{-# LANGUAGE DeriveDataTypeable, ScopedTypeVariables, TypeOperators, GADTs #-}
module FromConstr where
import Data.Data
data D = D String | AnyD deriving (Show, Data)
foo :: D
foo = fromConstrB field ctor
where
ctor :: Constr
ctor = toConstr (D "aaa")
field :: forall a. Data a => a
field = case eqT :: Maybe (a :~: String) of
Just Refl -> "new string"
Nothing -> error "trying to fill a non-string field"
如果构造函数有更多参数,则只需将列表变长,如[toDyn“string”、toDyn(42::Int)、toDyn True]
中所示。toDyn
函数将类型化值转换为“非类型化”值,以便它们可以一起存储在同一列表中,并传递给applyConstr
。稍后,applyConstr
将(在运行时)测试此列表的长度是否准确,是否具有正确类型的值。具有类型的定义
class C a where
anyC :: a
data D = D String|AnyD deriving (Eq, Show, Data)
instance C D where
anyC = AnyD
承诺提供任何类型的值a
,只要它在类C
内。foo
的用户可以选择a
,foo
本身无法选择特定类型
使用您的设置,唯一可能的(非错误)定义是
foo :: C a => a
如果要返回D“hello”
,则这是D
类型。如果需要,可以使用该类型:
foo = anyC
还请注意,如果需要,还可以更改实例:
bar :: D
bar = D "hello"
关于
在大多数现代语言中,这很容易
事实并非如此。例如,在Java中,一个模糊的等价物可以是
//类型类,大致如下
接口C{
A anyC();
}
类D实现C{…}
阿福(){
返回新的D(…);
}
Java也不会接受这一点。除了其他问题,foo()
承诺返回调用者选择的任何A
,但它不能选择返回D
Haskell类型变量大致对应于Java的泛型类型参数。您可能会转而考虑子类型,它存在于Java和其他OOP语言中,但Haskell没有使用
如果您想要一个来自constrb的示例,您可以尝试以下方法:
instance C D where
anyC = D "hello"
foo
计算结果为D“新字符串”
。这可以通过嵌套case eqT
s进行扩展,以便field
覆盖更多类型(如果构造函数需要更多类型),以便我们检查所有需要的类型
还要注意,fromConstrB的是有限的,因为如果我们的构造函数有两个相同类型的字段,我们就不能用不同的值填充字段。为此,我认为,我们需要从constrm
中求助于更复杂的
这里有一个小的方便助手函数。它接受一个Constr
,以及一个“非类型化”参数列表(Dynamic
在运行时进行所有类型检查),并尝试构建一个将构造函数应用于给定参数的值
{-# LANGUAGE DeriveDataTypeable, ScopedTypeVariables, TypeOperators, GADTs #-}
module FromConstr where
import Data.Data
data D = D String | AnyD deriving (Show, Data)
foo :: D
foo = fromConstrB field ctor
where
ctor :: Constr
ctor = toConstr (D "aaa")
field :: forall a. Data a => a
field = case eqT :: Maybe (a :~: String) of
Just Refl -> "new string"
Nothing -> error "trying to fill a non-string field"
如果构造函数有更多参数,则只需将列表变长,如[toDyn“string”、toDyn(42::Int)、toDyn True]
中所示。toDyn
函数将类型化值转换为“非类型化”值,以便它们可以一起存储在同一列表中,并传递给applyConstr
。稍后,applyConstr
将(在运行时)测试此列表的长度是否准确,是否具有正确类型的值。我的问题是如何使用简单(内置)类型调用fromConstrB
,而不是类型类