繁体   English   中英

在List的元素上定义约束函数?

[英]Define Function with Constraint on List's Elements?

如何使用以下签名定义函数,

f :: [Int???] -> [Int]
f xs = _ -- what I do with xs doesn't matter for the question

其中aInt的列表

这样第一个参数的输入(即列表元素)必须>= 0 ,而在编译时<= 5

换一种说法,

f [6]将无法编译。

怎么样:

f :: [Int] -> [Int]
f = filter (\x -> x >= 0 && x <= 5)

还是要对类型(相关类型)强制执行边界?

如果要限制允许的Int范围,最好使用智能构造函数 在这里看看。 这个想法是您创建自己的数据类型和自己的自定义构造函数:

newtype Range0_5 = Range0_5 { unRange :: Int }

makeRange0_5 :: Int -> Maybe Range0_5
makeRange0_5 x
  | x >= 0 && x <= 5 = Just $ Range0_5 x
  | otherwise        = Nothing

如果您创建了一个聪明的构造函数 ,那么不要将其暴露给模块的用户就很重要。 只需不导出Range0_5构造函数即可完成此操作。

但是,这不是编译时检查。 如果您确实需要这样的功能,则Haskell以外的其他语言可能更合适。

由于范围很小,因此您也可以创建一个求和类型来表示它:

data Range0_5 = Int0 | Int1 | Int2 | Int3 | Int4 | Int5

如果签名是

f :: [Int] -> [Int]

(这是问题的原始形式),那么就不可能在编译时强制执行约束。 这是从Halting问题的标准对角化论点得出的

假设编译器可以检测到

f[g x]

不应该编译。 通过将编译器的源代码合并到g ,它可以选择与编译器决定相反的选项。


在您对Liquid Haskell (似乎是一个非常有趣的项目)发表评论之后,请注意以下几点:

{-@ type Even = {v:Int | v mod 2 = 0} @-}

{-@ foo :: n:Even -> {v:Bool | (v <=> (n mod 2 == 0))} @-}   
foo   :: Int -> Bool 
foo n = if n^2 - 1 == (n + 1) * (n - 1) then True else foo (n - 1)

LiquidHaskell声称此函数不安全,因为可能foo n调用foo (n - 1) 但是请注意,这绝不会发生:它只能被称为如果关系N 2 - 1≠(N + 1)(N - 1),这可能永远不会发生。

再次,这不是对LiquidHaskell质量的批评,而是仅仅指出它也不能解决类似问题的停止问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM