我正在尝试编写一个函数,用于评估嵌套的布尔数据类型。我的问题来自比较数据类型内的数据类型。前两个(Lit和Or)可以很好地编译,但是我不明白如何将第一个类型合并到SecondExpr的函数中。当我输入内容时,我觉得当一些较短的方法可行时,我正在采取最长的方法。
这是两种数据类型。
data Expr = Val Int
| Add Expr Expr
| Sub Expr Expr
| Mul Expr Expr
| Div Expr Expr
| If SecondExpr Expr Expr
data SecondExpr = Lit Bool
| Or SecondExpr SecondExpr
| EqualTo Expr Expr
| LessThan Expr Expr
(我遇到的另一个问题是创建SecondExpr的示例进行测试,因为从概念上讲,我将每个Expr视为6种不同类型的Expr。这意味着,对于每个Expr Expr,都会有数百个防护。)>
下面是到目前为止的代码:
eval :: SecondExpr -> Bool
eval (Lit n) = n
eval (Or e1 e2)
| True && True = True
| True && False = True
| False && True = True
| otherwise = False
eval (EqualTo e1 e2)
| (Add e1 e2) == (Add e1 e2) = True
| (Sub e1 e2) == (Sub e1 e2) = True
| (Mul e1 e2) == (Mul e1 e2) = True
| (Div e1 e2) == (Div e1 e2) = True
| otherwise = False
eval (LessThan e1 e2)
| (Add e1 e2) == (Add e1 e2) = True
| (Sub e1 e2) == (Sub e1 e2) = True
| (Mul e1 e2) == (Mul e1 e2) = True
| (Div e1 e2) == (Div e1 e2) = True
| otherwise = False
这是我得到的错误:
* No instance for (Eq Expr) arising from a use of `=='
* In the expression: (Add e1 e2) == (Add e1 e2)
In a stmt of a pattern guard for
an equation for `eval':
(Add e1 e2) == (Add e1 e2)
In an equation for `eval':
eval (EqualTo e1 e2)
| (Add e1 e2) == (Add e1 e2) = True
| (Sub e1 e2) == (Sub e1 e2) = True
| (Mul e1 e2) == (Mul e1 e2) = True
| (Div e1 e2) == (Div e1 e2) = True
| otherwise = False
|
24 | | (Add e1 e2) == (Add e1 e2) = True
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
所以我知道我的语法是错误的,但是如何在表达式的功能内替换表达式?
答案 0 :(得分:5)
您将需要两个评估功能:
# -*- mode: ruby -*-
# vi: set ft=ruby :
# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure("2") do |config|
# The most common configuration options are documented and commented below.
# For a complete reference, please see the online documentation at
# https://docs.vagrantup.com.
# Every Vagrant development environment requires a box. You can search for
# boxes at https://vagrantcloud.com/search.
config.vm.box = "jaxmetalmax/debian8-rubydev"
# Disable automatic box update checking. If you disable this, then
# boxes will only be checked for updates when the user runs
# `vagrant box outdated`. This is not recommended.
# config.vm.box_check_update = false
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine. In the example below,
# accessing "localhost:8080" will access port 80 on the guest machine.
# NOTE: This will enable public access to the opened port
# config.vm.network "forwarded_port", guest: 80, host: 8080
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine and only allow access
# via 127.0.0.1 to disable public access
# config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"
# Create a private network, which allows host-only access to the machine
# using a specific IP.
# config.vm.network "private_network", ip: "192.168.33.10"
# Create a public network, which generally matched to bridged network.
# Bridged networks make the machine appear as another physical device on
# your network.
# config.vm.network "public_network"
# Share an additional folder to the guest VM. The first argument is
# the path on the host to the actual folder. The second argument is
# the path on the guest to mount the folder. And the optional third
# argument is a set of non-required options.
# config.vm.synced_folder "../data", "/vagrant_data"
config.vm.synced_folder "C:/EGodoy/Sites", "/home/vagrant/sites"
config.vm.network "private_network", ip: "192.168.33.10"
# Provider-specific configuration so you can fine-tune various
# backing providers for Vagrant. These expose provider-specific options.
# Example for VirtualBox:
#
# config.vm.provider "virtualbox" do |vb|
# # Display the VirtualBox GUI when booting the machine
# vb.gui = true
#
# # Customize the amount of memory on the VM:
# vb.memory = "1024"
# end
#
# View the documentation for the provider you are using for more
# information on available options.
# Enable provisioning with a shell script. Additional provisioners such as
# Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
# documentation for more information about their specific syntax and use.
# config.vm.provision "shell", inline: <<-SHELL
# apt-get update
# apt-get install -y apache2
# SHELL
end
和
evalNum :: Expr -> Int
他们都不应该使用任何防护装置(evalBool :: SecondExpr -> Bool
)。
例如,| ...
如下所示:
evalBool
使用相应的evalBool (Lit n) = n
evalBool (Or e1 e2) = evalBool e1 || evalBool e2
evalBool (EqualTo e1 e2) = evalNum e1 == evalNum e2
evalBool (LessThan e1 e2) = evalNum e1 < evalNum e2
函数对子表达式进行递归求值,并使用适当的Haskell运算符(例如eval
,||
,==
)对结果进行组合。
<
的实施留给读者练习。