Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 如何写一个“";从「;及;至;“的函数”;添加Void a==a";?_Haskell_Algebraic Data Types - Fatal编程技术网

Haskell 如何写一个“";从「;及;至;“的函数”;添加Void a==a";?

Haskell 如何写一个“";从「;及;至;“的函数”;添加Void a==a";?,haskell,algebraic-data-types,Haskell,Algebraic Data Types,从文件:,它说: Bool和Add()是等价的,因为我们可以定义“from”和“to”函数: to :: Bool -> Add () () to False = AddL () to True = AddR () from :: Add () () -> Bool from (AddL _) = False from (AddR _) = True 即: from (to a) == a to (from a) == a 然后他又给出了两个: Add Void a ===

从文件:,它说:

Bool和Add()是等价的,因为我们可以定义“from”和“to”函数:

to :: Bool -> Add () ()
to False = AddL ()
to True  = AddR ()

from :: Add () () -> Bool
from (AddL _) = False
from (AddR _) = True
即:

from (to a) == a
to (from a) == a
然后他又给出了两个:

 Add Void a === a
 Add a b === Add b a
如何为这两个函数编写“from”和“to”函数

添加b===添加b a

您需要交换
AddL/AddR
构造函数,如下所示:

to :: Add a b -> Add b a
to (AddL x) = AddR x
to (AddR x) = AddL x

-- from = to
为了

添加Void a==a

您需要一个多态函数
void:void->a

to :: Add Void a -> a
to (AddL impossible) = void impossible
to (AddR x) = x

from :: a -> Add Void a
from x = AddR x
变量
impossable
表示类型为
Void
的“不存在”值。实际上没有这样的值(除了底部/未定义)。这就是为什么要排队

to (AddL impossible) = ...
实际上是不可访问的代码——它永远不会被执行

函数
void
利用了一个事实,即它需要一个不可能的参数来凭空生成一个值
a
。不幸的是,在Haskell中,
void
无法定义,除非利用不确定性,例如

void :: Void -> a
void _ = error "This will never be reached"
一个更优雅、更正确的解决方案是

void :: Void -> a
void x = case x of
           -- no constructors for Void, hence no branches here to do!
           -- since all these (zero) branches have type `a`, the whole
           -- case has type `a` (!!!)

但是,遗憾的是,Haskell禁止空的
case
构造。(在GHC 7.8中,如前所述,通过扩展允许使用空箱)

相比之下,在Coq或agda等依赖类型的语言中,上面的代码(稍加修改)就可以了。下面是Coq中的:

Inductive Void : Set := .   (* No constructors for Void *)

Definition void (A : Set) (x : Void) : A :=
      match x with
      end .
在阿格达

data Void : Set where
   -- no constructors

void : (A : Set) -> Void -> A
void A ()         
-- () is an "impossible" pattern in Agda, telling the compiler that this argument
-- has no values in its type, so one can omit the definition entirely.
该库具有类型为
Void->a
的函数。它抓住了“从错误开始,一切都遵循”的逻辑原则

它可用于从总和类型中删除
Void
分支。直观地说,如果您的类型是
a
或不可能的类型,那么它与
a
几乎相同

import Data.Void

foo :: Either Void a -> a
foo x = either absurd id x 

“但是,遗憾的是,Haskell禁止空的
大小写
构造。”不再是了,在7.8中,我们现在有了,它给出了一个特别针对
Void
的示例。我试图调用
到(AddL 1)
,但它报告:
没有由literal 1产生的(Num a0)实例,类型变量
a0'是不明确的”。如何给它一个正确的参数?@Freewind使用
to(AddL(1::Int))
来指定
1
的类型。Haskell抱怨是因为
1
周围的上下文不允许理解
1
是否应该是
Int
Double
或任何其他数字类型。