“我接触了haskell,它对功能类型有强烈的倾向,因为我想学习功能类型。但是,我感到沮丧,因为它与现有的功能类型太不同了。”
“我不知道学习这些后能做什么。”
我认为有很多这样的人。
另外,目前,它有时是与球体理论一起讨论的,因此对于某些人来说,掌握轮廓并在不知不觉中避开它可能会更加困难。
因此,在本文中,我将以一种易于理解的方式从haskell的环境构造中解释功能类型的概念和优点。
什么是Haskell
haskell是功能性编程语言之一,并且是一种具有严格遵循纯功能性功能思想的语法和机制的编程语言。
如今,前端榆树也是受haskell影响很大的一种语言。
正如我将在后面详细解释的那样,它只是一个纯函数类型,其特点是具有许多函数类型函数并限制了面向对象的编写。
什么是函数类型?
首先,让我们解释一下可以说是源代码的功能类型。
简而言之,功能类型的想法是``将功能的副作用减少到最大程度''。
首先。当前的编程具有以下特性:函数的行为是调用该函数的黑匣子。
结果,我不知道执行该功能的结果在哪里受到影响,并导致了错误。至少我有很多实际的想法和经验。
让我举几个例子。
$test = 10; function change(){ $test = 100; } //main処理 change(); print ($test) // 100
上面有一个由函数修改的全局变量。很好,因为函数的声明是一组编写的,
//main処理 change(); print ($test) // 100
如果仅切出一部分,您可能会想知道更改功能在做什么,并且很难获得代码概述。
这是该功能的副作用及其有害影响。关键是在执行该函数之前和之后,它将影响除返回点以外的其他部分。
当然,上面的示例在一定程度上可以通过适当的注释和命名约定来涵盖,但可悲的是人类是会犯错误的生物。
由于人为错误的性质,继续按照特定规则行事是困难的,并且检查这些错误的努力会增加成本。
因此,函数类型的想法是简单地编写或强制代码以通过编程语法来减少此类函数的副作用以减少函数的副作用。
haskell(它的好处)
正如我之前所说,haskell具有故意限制现有的面向对象的写作风格的特征。
通过这样做,该语言迫使您不要实现所谓的反模式(例如副作用太大而无法维护)。
因此,如果您知道如何编写haskell以及如何思考它,您将强烈意识到在面向对象上通常不会注意到的副作用,尤其是在设计和测试部件中。
您可以利用这些知识。
现在,让我们介绍一下面向对象方面的一些著名点以及它与其他语言的不同之处。
变量
- 1.无法重新分配
- 2.初始化只能执行一次
- 3.延迟评估
与其他功能语言一样,它具有禁止重新分配的特征。
除此之外,它还具有称为延迟评估的独特机制。
简而言之,只有在需要变量时才对其求值。
就此而言,haskell可以完成这项工作而无需任何额外的工作。
(它很容易变成无限循环...)
功能
- 1.如何调用灵活的功能,例如左联接,右联接,中间联接等。
- 2.增强的功能,用于由守卫根据参数的值进行模式匹配和分支处理
让我们实际触摸一下此功能的功能。它们配备了函数,可以分层调用函数并简化函数的定义。
单子
- 1.能够隐藏副作用的能力
- 2.一个专门用于从1.对象中检索值的接口
我将分别介绍Monad。
什么是莫纳德?
好吧,我说功能类型可以减少副作用,但是有一个问题。
通过减少副作用,它使某些代码变得多余。
首先,例如,连接数据库或读取或写入文件都有副作用,因为每次执行功能时,它们都会影响某些状态变量。
这意味着您将无法以完全功能的语言使用这些操作。
(如果将所有处理都放在主函数中可能是不可能的,但是我讨厌强迫这样的代码的编程语言)
因此,诸如monads和action之类的功能应运而生。
作为图像,我们包装了一个具有副作用的函数(简而言之,它具有一些状态变量并对其进行修改以进行处理),以便从中获取值。
这种包裹通过限制副作用的范围来使影响最小化。
如果您只是听这个故事,可能听起来就像只是封装在一个类中。
实际上,这个想法本身就已经存在了,这个想法是通过将副作用限制在特定范围内来消除外界的副作用。
但是,其特点是它专门提取值。
环境
让我们构建环境。
这次我想尽可能地专注于解释
使用称为堆栈的工具。
这可以吸收操作系统和hakell版本之间的差异,并稳定地启动haskell。
如果设置成功完成
Unix类型(包括mac)类型
curl -sSL //get.haskellstack.org/ | sh
要么:
wget -qO- //get.haskellstack.org/ | sh
请点击终端
对于Windows,请从下面的官方文档下载Windows安装程序
请开始。
//docs.haskellstack.org/en/stable/README/#how-to-install
如果可以成功安装
stack --version
您可以在以下位置查看版本。
以及如何做
stack runghc `file-name`
例如,准备此文件test.hs
main = do print "hello world"
并从终端
stack runghc test.hs
让我们一起运行。
"hello world"
显示成功。
主功能
让我们实际说明haskell的语法。
如果您从一开始就想起所有事情,那会造成混乱,因此,我将重点介绍与功能概念相近的内容。
首先,让我们定义一个函数。
由于haskell将所有内容都表示为一个函数,因此首先要确定要执行的函数。
这称为主要功能。
并这样写。
main = do // メイン関数処理
如果主要功能的处理是一行,则忽略这样做并应用。
main = // メイン関数処理
从现在开始,除非另有说明,否则可以编写出现在主函数中的处理。
变量
宣言
该声明声明了这样的变量和类型。
variable :: Int
初始化
您可以输入这样的值并将其初始化。由于hskqll具有类型推断,因此可以在不声明和键入的情况下对其进行初始化。
variable = "string"
顶级变量
就像全局变量的haskell版本一样
variable = 100 * 5 main = do print variable
这样,您可以通过在函数范围之外声明它来从任何函数中读取值。
顺便说一句,此haskell不像其他语言一样具有将值存储在存储区中的属性,但是它存储表达式本身并在调用表达式时对其进行求值。
例如
variable = 100 * 5 print variable
如果是这样,则变量的公式为100 * 5,而不存储值500。
使用打印变量评估该变量,并将其传递给要在控制台屏幕上显示的函数的参数。
只有这样,才可以计算和给出值。
在这种情况下,haskell有时称为绑定而不是分配值。
功能
让我们看一下主要功能。
也就是说,当它是主要功能时,我将对其进行一些介绍,因此将其包括在内。
另外,由于功能是主要的,因此有许多特殊的语法。
但是,这次我们仅介绍基本功能和特征功能。
定义
在一行的情况下
function = // 処理
对于多行
function = do // 処理
如果有争论
add x y = x + y print (add 1 3)
呼叫
声明和带参数调用
功能的左联接,右联接
print (add 1 3)
至于上半部分,在haskell中,函数按从左到右的参数顺序一个接一个地求值,那么,如果您编写print add 1 3会发生什么?
按(((打印添加)1)3。将会发生错误。
因此,将函数的参数部分+参数部分包含在()中或使用运算符$。
由于$指定此后的函数按从右到右的顺序进行求值,因此print $ add 1 3也将正常求值。
模式匹配
您想要使用特定的参数执行特定的过程是很自然的。
haskell将其纳入语法中。
模式匹配在参数具有特定值的条件下分支过程。
printdata :: Integer -> String printdata 10 = "ten" printdata 100 = "hundred" variable = variable * 5 main = do print (printdata 10)
守卫
守卫根据特定参数的范围分支该过程。
printdata :: Integer -> String printdata num | num > 10 = "ten" | num > 100 = "hundred" | otherwise = "???" variable = variable * 5 main = do print (printdata 10)
从要使用的变量下面一行
|表达式=值
该过程以的形式分支。
如果它不适合任何范围
|否则=值
描述过程。
部分申请
除非具有所有必需的参数,否则面向对象的函数无法执行函数。
但是,haskell可以部分应用一项功能并生成一个新功能。
main = do print value where by3 = by 3 value = by3 4 --12
这样,您可以通过仅传递第一个参数并固定值来创建新函数。
单子
我认为,如果仅解释功能,有些部分将很难理解,因此
这次,作为示例,我将编写一个monad,该monad从随机数接收一个值并返回一个字符。
import System.Random randomNum = do number <- getStdRandom ( randomR (0,99)) :: IO Int case number of _ | number > 50 -> return "high" :: IO String | otherwise -> return "low" :: IO String main = do print =<< randomNum var <- randomNum print var
为了简单起见,我们将使用现有的随机库。
randomNum = do number <- getStdRandom ( randomR (0,99)) :: IO Int case number of _ | number > 50 -> return "high" :: IO String | otherwise -> return "low" :: IO String
上面的部分生成一个随机数,如果大于或等于50,则返回字符串高;如果小于或等于50,则返回低字符串。
结果以字符串形式返回。
应该检查
| number > 50 -> return "high" :: IO String | otherwise -> return "low" :: IO String
这是返回的一部分。
这定义了它以monad的形式返回值,
randomNum是一个monad,而不是一个函数。
接下来的部分是检索数据。
main = do print =<< randomNum var <- randomNum print var
如您所见,与函数不同,我们使用唯一的运算符来检索值。
如果您只是想检索值并将其绑定到变量
var <- randomNum
喜欢<-という演算子を使っています。
另一方面,如果要将提取的值原样传递给另一个函数的参数
print =<< randomNum
使用称为的唯一运算符。
有待进一步研究
这次,我们仅介绍了开发环境和haskell等特征性的东西。
因此,在此之后,我将发布材料进行详细研究。
教程
向您了解Haskell的伟大成就!
尽管它是英语,但是仍然有大量的示例说明和详细的说明,因此即使您只是阅读它,
这将是一个很好的研究。
演练Haskell
Haskell信息以日语编写。
它更像一个文档,但是由于规范和示例代码的构造,因此非常易于阅读。
如果您只想查看概述,那么这里是快速阅读的好地方。
构架
haskell仍然是次要语言,但是有几个框架。
作为著名的地方,前端 味噌
Web应用程序 耶索德
此外,榆木(现在成为热门话题)也受到haskell的影响。
也许如果您想这样做,可以创建一个应用程序,其中所有前台和服务器都装有haskell。
最后
最后但并非最不重要的一点是,功能类型当然很棒,但这绝不是通用的。
实际上,功能类型最近引起了人们的关注,因此,与主要语言相比,haskell和其他语言还没有处于开发环境中。
因此,如果您尝试将其引入您的项目中,将没有太多文档可以解决问题。
但是,通过触摸功能类型,您可以提醒自己,当您触摸对象类型时,它不会引起副作用,因此,您将能够编写高度可维护且易于编写测试的代码。您可以期望的足够。
概要
怎么样
由于功能类型,单子和球体理论的混乱,我觉得不必要地提高了这些障碍,所以我希望我可以尽可能地降低这些障碍。