非负整数

时间:2010-01-15 11:09:19

标签: haskell types

假设我有一个函数原型如下:

func :: [Int] -> [Int]

如何仅将非负的整数列表强制实施为输入参数?我必须将[Int]的param类型改为什么..?在这个公平的时刻,它与func [-1,-2]一起工作,我只希望它与[1,2]一起使用,即解释器喷出错误信息。

5 个答案:

答案 0 :(得分:7)

newtype NonNegative a = NonNegative a

toNonNegative :: (Num a, Ord a) => a -> NonNegative a
toNonNegative x
  | x < 0 = error "Only non-negative values are allowed."
  | otherwise = NonNegative x

fromNonNegative :: NonNegative a -> a
fromNonNegative (NonNegative x) = x

请注意不要直接使用NonNegative构造函数。如果将其放在单独的模块中并且不导出它,这将更容易。

此外,现在您可以使用(map toNonNegative)来懒惰地转换数字列表。

无论您在哪里注入原始数字,都仍需要运行时检查。

或者,您可以使用Data.Word。

答案 1 :(得分:4)

答案 2 :(得分:1)

您可以使用Peano numbers,将您的函数类型更改为[Peano] -> ...。但是,无论何时调用函数,都必须将转换函数从整数添加到peano数字并返回。

或者您可以添加运行时检查:

func xs
  | any (< 0) xs  = error "only non-negative integers allowed as input"
  | otherwise     = ...

请注意,后一种解决方案会使您的函数strict

答案 3 :(得分:1)

smart constructors上的维基页面可能会给你一些想法。

答案 4 :(得分:0)

在GHC 7.10.1及更高版本中包含版本&gt; = 4.8.0.0的基本软件包中,现在有一个Natural类型可以满足您的需求 - 您只需将代码更改为:

import Numeric.Natural (Natural)

func :: [Natural] -> [Int]

然而,它更接近Integer而不是Int,因为与Integer类似,与Int不同,它没有最大值。

因为NaturalInteger一样,是NumIntegral的一个实例,所有相同的算术运算和转换函数都可用{{1} }}。尝试计算负Integer将在运行时抛出Natural,这是Underflow。此外,方便的是,您可以仅使用整数文字创建ArithException,而无需转换:

Natural

但是,如果您希望保留固定大小的整数域,那么也有一个解决方案 - 它已经存在了很长时间 - GHCi, version 8.0.2: http://www.haskell.org/ghc/ :? for help Prelude> :m +Numeric.Natural Prelude Numeric.Natural> 2 :: Natural 2 来自the module Data.Word(对于8位非负整数,它还包含例如Word。您可以像Word8一样使用Word。但是,请注意 - Natural类型将以静默方式下溢,而不会抛出异常:

Word