在很多关于Haskell的文章中,他们说它允许在编译时而不是运行时进行一些检查.所以,我想实现最简单的检查 - 允许只在大于零的整数上调用一个函数.我该怎么做?
如何通过专用功能强制创建Discriminated Union值?
意图:
我想依靠Creational Patterns来生成只有有效数据的结构.
因此,我认为我需要通过将其设为只读来限制DU值的使用.但是,对我来说,如何实现这一目标并不明显.
module File1 =
type EmailAddress =
| Valid of string
| Invalid of string
let createEmailAddress (address:System.String) =
if address.Length > 0
then Valid address
else Invalid address
module File2 =
open File1
let validEmail = Valid "" // Shouldn't be allowed
let isValid = createEmailAddress ""
let result = match isValid with
| Valid x -> true
| _ -> false
Run Code Online (Sandbox Code Playgroud)
我尝试了以下方法:
type EmailAddress =
private
| Valid of string
| Invalid of …Run Code Online (Sandbox Code Playgroud) 我的代码中有几个域类型用于区分不同类型的字符串,因此编译器可以阻止我以错误的顺序传递参数:
type Foo = string
type Bar = string
let baz (foo : Foo) (bar : Bar) = printfn "%A %A" foo bar
let f : Foo = "foo"
let b : Bar = "bar"
baz f b // this should be OK
baz b f // this shouldn't compile
Run Code Online (Sandbox Code Playgroud)
但是,这目前无法令人满意地工作,原因有两个:
null不是有效值的方法,所以我不能保证Foo实例永远不会null.有没有办法定义类型别名
a)引用/包装相同类型,但彼此不兼容,并且b)禁止null值,即使基础类型允许它?
我是Haskell的新手,想知道是否可以定义一个仅在已有类型的子集上定义的函数,而不必实际定义新类型.
示例:我想创建一个只接受整数(甚至是自然数等)的函数并返回,例如,这个数字的平方,如:
squared :: 2*Integer -> Integer
squared n = n*n
Run Code Online (Sandbox Code Playgroud)
当然,以上两行不起作用.
我知道我可以这样写:
squared' :: Integer -> Integer
squared' n
| (even n) = n*n
| otherwise = error "n is not even!"
Run Code Online (Sandbox Code Playgroud)
或类似的东西,但我想知道是否有可能像非工作示例这样的东西.
我希望这个问题不是完全愚蠢的(或者已经回答过了)但是我真的不知道很多Haskell(所以寻找答案也有点困难)......