导出函数在第一个概念中已经讲过,这里快速回顾一下。
Elm 中的每个文件都是一个模块,并且必须在所有其他代码之前包含一条 module 语句。
模块名必须与文件名一致,所以模块 Calculator 必须放在文件 Calculator.elm 中,模块 Parser.Utils 必须放在文件 Parser/Utils.elm 中。
模块中定义的所有内容都只属于该模块的私有作用域,除非在 exposing 中列出,否则无法从模块外部访问。
-- Calculator.elm
-- Define the Calculator module, and expose the `add` function
module Calculator exposing (add)
six = 3 + 3
add number1 number2 = number1 + number2
-- Calculator.elm
-- Define the Calculator module, and expose everything within: `six` and `add`
module Calculator exposing (..)
six = 3 + 3
add number1 number2 = number1 + number2
https://elm-lang.org/docs/syntax#modules
要访问其他模块中定义的函数,需要通过导入来实现。 导入某个模块时,该模块公开的所有函数都会变得可以访问。 但访问它们的方式取决于模块的导入方式。
默认是限定导入,访问这类模块中的函数(例如 List 模块中的 map 函数)时,需要在前面加上模块名(List.map)。
开放导入可以直接访问该模块中公开的函数,无需加前缀。使用 exposing 关键字即可,它与导出时用的那个关键字正好相对。你可以公开所有可用的函数(用 ..),也可以只公开特定的函数(例如 map)。
你还可以从其他模块导入类型及其构造函数,这会在后面的概念中讲到。
推荐使用限定导入,这样更清晰,也能避免命名冲突。
-- qualified imports
import List -- List.map, List.foldl
import List as L -- L.map, L.foldl
-- open imports
import List exposing (..) -- map, foldl, concat, ...
import List exposing ( map, foldl ) -- map, foldl, List.concat
https://elm-lang.org/docs/syntax#modules
类型注解的写法是 name : parameter types -> return type,多个形参类型之间也用 -> 分隔。
add : Int -> Int -> Int
add number1 number2 = number1 + number2
可以用括号来定义函数的形参(形参本身也用同样的语法定义,所以才需要括号)。
-- Transform every character in a string
map : (Char -> Char) -> String -> String
map charMapperFunction string =
-- ...
https://elm-lang.org/docs/syntax#type-annotations
Elm 中有两种数字类型,分别由 Int 和 Float 类型定义。
Int 对应正整数和负整数组成的集合。
Float 对应实数集合,受计算机精度的限制。
为数字定义的运算通常只适用于其中一种类型,不能把两者混用。
也有一些函数可以在两者之间转换:toFloat 把 Int 转换为 Float,而 round、floor、ceiling 或 truncate 则以各自的语义把 Float 转换为 Int。
https://package.elm-lang.org/packages/elm/core/latest/Basics#Int
为了在代码中表示单词和句子,Elm 有一个原生的 String 类型。
字符串字面量写在双引号之间,例如 "Hello World!"。
默认可以使用字符串拼接运算符 ++ 和相等运算符 ==。
hello : String -> String
hello subject = "Hello " ++ subject
hello "World!" --> "Hello World!"
其他大多数字符串函数都在 String 模块中,需要先导入才能使用。
https://package.elm-lang.org/packages/elm/core/latest/String
在这个练习中,你将编写一些代码来帮助 Betty's Bike Shop,这是一家在线销售自行车和配件的商店。 你有三个任务,目标是在网站上正确地显示自行车和配件的价格。
penceToPounds函数你的同事已经写好了这个模块的骨架,即两个尚未定义的函数penceToPounds和poundsToString。
但是,他们忘了导出penceToPounds函数,所以它目前对其他模块和测试套件都不可见。
把penceToPounds加入导出函数的列表。
目前,价格以整数形式的便士存储(这家自行车店位于英国)。
在网站上,我们希望以英镑显示价格,其中 1.00 英镑等于 100 便士。
你的第二个任务是实现penceToPounds函数,它接收以Int表示的便士数量,并将其换算成等值的英镑,以Float返回。
你还应该为这个函数定义类型标注。
penceToPounds 106
--> 1.06
由于 Betty's Bike Shop 的自行车以英镑出售,价格显示时应带上符号“£”。
因此,你的第三个任务是实现poundsToString函数,它接收以Float表示的英镑数量,并返回一个String,即前面加上英镑符号的价格。
String模块里有String.fromFloat函数,会对你有帮助。
使用String模块之前,你应该先导入它。
你还应该为poundsToString定义类型标注。
poundsToString 1.06
--> "£1.06"