Haskell:元组的递归定义

时间:2019-04-02 17:02:04

标签: haskell recursion lambda-calculus

我正在尝试创建Krivine抽象机。我需要构建的数据类型之一是环境。这样构建环境:

我们有x,一个“ Var”(这只是字符串的同义词) 我们有N个“术语”(这是Lambda术语)

所以环境E的定义是:

E =(x,N,E)·E。

因此,环境是元组列表。每个元组包含一个Var(字符串),一个Term和一个环境列表(可能为空)。

我正在这样定义“ Env”:

data Env = Env (Var, Term, [Env])

在我看来,这似乎应该可以工作。但是,当我尝试使用Env时,会得到:

*Main> ("y", Lambda "z" (Variable "z"), []) :: Env

<interactive>:166:1: error:
* Couldn't match expected type `Env'
              with actual type `([Char], Term, [a0])'
* In the expression: ("y", Lambda "z" (Variable "z"), []) :: Env
  In an equation for `it':
      it = ("y", Lambda "z" (Variable "z"), []) :: Env

“ y”当然是[字符]

Lambda“ z”(变量“ z”)的类型肯定是Term

一个空列表绝对是一个列表!

我觉得问题可能出在空列表上,但是在环境中可以存在一个空列表是绝对必要的(这是基本情况)。

我现在一直在努力工作几个小时,一点也​​不运气。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:8)

Env

在这里定义类型Env和数据构造函数Env。它们具有相同的名称,但是数据构造函数ghci> :t Env Env :: (Var, Term, [Env]) -> Env 是类型为

的值
Env

构造函数定义从元组到Env值的映射。它也可以用于模式匹配,以将ghci> :t \(Env t) -> t \(Env t) -> t :: Env -> (Var, Term, [Env]) 值映射到元组:

Env

诀窍在于,尽管类型(Var, Term, [Env])的值与元组Env同构,但它们具有不同的类型。 data SecondsAfterMidnight = SecondsAfterMidnight Int data PenniesPerHour = PenniesPerHour Int 。这是主语类型,而不是结构类型。当我们希望在内部具有相同结构但在类型系统中不同的值时,这非常有用。

fiveCentsPerHour + oneFifteenAM

这阻止我们执行类似String的操作。

也就是说,有时候您只想为复杂类型使用一个更方便的名称,而又不想与复杂类型区分开。 Haskell具有类型别名来处理这种情况。例如,[Char]type(字符列表)的类型别名;它们是相同类型的两个名称。

如果它不是递归的,并且您不想打扰构造函数,则可以使用type Env = (Var, Term, [SomethingElse]) 关键字来使用类型别名:

Env

但是您不能使用类型别名来定义递归类型,因为它们会在编译时无限扩展。

您可以采用的另一种方法是放弃元组并拥抱data Env = Env Var Term [Env] 构造函数:

Env

现在ghci> :t Env Env :: Var -> Term -> [Env] -> Env 构造函数采用三个参数,而不是元组。

data Env = Env { var :: Var, term :: Term, env :: [Env] }

您还可以使用记录语法来获取各个字段的getter:

ghci> :t var
var :: Env -> Var
ghci> :t term
term :: Env -> Term
ghci> :t env
env :: Env -> [Env]

这些非常方便:

import base64

@app.route('/uploader', methods = ['GET', 'POST'])
def uploaded_file():
    if request.method == 'POST':
    photo = request.files['file']
    in_memory_file = io.BytesIO()
    photo.save(in_memory_file)
    data = np.fromstring(in_memory_file.getvalue(), dtype=np.uint8)
    color_image_flag = 1
    img = cv2.imdecode(data, color_image_flag)
    frame,res=recogn(img)

    imencoded = cv2.imencode(".jpg", frame)[1]

    jpg_as_text = base64.b64encode(imencoded)

    return render_template('from_file.html', photo=jpg_as_text)