在Type Driven Development with Idris第6章的代码中,我对这段代码感到困惑:
data DataStore : Type -> Type where
MkData : (size : Nat) ->
(items : Vect size schema) ->
DataStore schema
我认为它可能无法编译,因为schema
似乎未定义或至少需要以某种方式绑定到DataStore
的第一个参数。但是,它加载很好,可以这样使用:
*DataStore> the (DataStore String) $ MkData 2 ["Fred", "Wilma"]
MkData 2 ["Fred", "Wilma"] : DataStore String
我认为DataStore
的第一个参数需要像schema
这样命名:
data DataStore : (schema : Type) -> Type where
MkData : (size : Nat) ->
(items : Vect size schema) ->
DataStore schema
此定义可以与初始定义类似地使用。
我想知道两个定义之间是否存在任何语义差异,以及是否有人可以帮助我解释我对schema
未定义的错误直觉。
答案 0 :(得分:4)
这里发生了两件事。第一个是隐含的论点。用作函数参数的小写名称始终转换为隐式参数。例如,函数组合运算符:
Idris> :t (.)
(.) : (b -> c) -> (a -> b) -> a -> c
Idris> :set showimplicits
Idris> :t (.)
Prelude.Basics.(.) : {c : Type} -> {a : Type} -> {b : Type} -> (b -> c) -> (a -> b) -> a -> c
compose的类型涉及变量a,b和c,它们在类型签名中的任何地方都没有声明。伊德里斯将它们变成隐含的参数 - 所有这些参数都具有类型Type
- 它将尝试通过统一来推断。 {curly brackets}
是显式指定隐式参数的语法。您始终可以在解释器中使用:set showimplicits
来查看它们。在DataStore
示例中,schema
是隐式变量。
当您调用包含它们的函数时,您也可以指定implicits:
λΠ> MkData {schema = String} 2 ["hi", "Steven"]
MkData 2 ["hi", "Steven"] : DataStore String
第二件事是data
声明中类型构造函数类型中的变量不限于除该类型构造函数之外的任何内容。你给出的DataStore
的第二个定义与原始定义完全相同,因为" schema" DataStore : (schema : Type) -> Type
中MkData
的类型签名范围内不在using System.Windows;
namespace YourNameSpace
{
/// <summary>
/// Add Proxy <ut:BindingProxy x:Key="Proxy" Data="{Binding}" /> to Resources
/// Bind like <Element Property="{Binding Data.MyValue, Source={StaticResource Proxy}}" />
/// </summary>
public class BindingProxy : Freezable
{
protected override Freezable CreateInstanceCore()
{
return new BindingProxy();
}
public object Data
{
get { return (object)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
public static readonly DependencyProperty DataProperty = DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy));
}
}
。