Haskell 我可以写这样的多态函数吗?我需要什么语言扩展?

Haskell 我可以写这样的多态函数吗?我需要什么语言扩展?,haskell,Haskell,我尝试编写了两个函数来正确解析数字,并进行了所有的检查(签名String->可能是a,用于某个a集合)。我已经编写了解析无界整数的函数(mayberadinteger),然后我想编写解析所有有界整数类型的多态函数:只需在某些范围检查中包装mayberadintegerMayberadNum试图编写这样的函数,但它不进行类型检查。可以这样写吗?我必须打开哪些语言扩展(如果有) splitIntoSignAndDigits str = case str of '-':rest ->

我尝试编写了两个函数来正确解析数字,并进行了所有的检查(签名
String->可能是a
,用于某个
a
集合)。我已经编写了解析无界
整数的函数(
mayberadinteger
),然后我想编写解析所有有界整数类型的多态函数:只需在某些范围检查中包装
mayberadinteger
MayberadNum
试图编写这样的函数,但它不进行类型检查。可以这样写吗?我必须打开哪些语言扩展(如果有)

splitIntoSignAndDigits str = case str of 
    '-':rest -> (-1, rest)
    '+':rest -> ( 1, rest)
    _        -> ( 1, str )

maybeReadUnsignedInteger []         = Nothing
maybeReadUnsignedInteger str@(x:xs) = go 0 str
    where go n str = case str of
              []                            -> Just n
              (x:xs) | '0' <= x && x <= '9' -> go (10 * n + digit) xs
                     | otherwise            -> Nothing
                  where digit = toInteger (ord x - ord '0')

maybeReadInteger str = fmap (sign*) (maybeReadUnsignedInteger str')
    where (sign, str') = splitIntoSignAndDigits str

maybeReadNum :: (Integral a, Bounded a) => String -> Maybe a
maybeReadNum = fmap fromInteger . 
               mfilter (\n -> n >= toInteger (minBound :: a) && 
                              n <= toInteger (maxBound :: a)) .
               maybeReadInteger
splitIntoSignAndDigits str=大小写str
“-”:rest->(-1,rest)
“+”:rest->(1,rest)
_->(1,str)
Maybreadunsignedinteger[]=无
Mayberadunsignedinteger str@(x:xs)=go 0 str
where go n str=案例str
[]->仅n
(x:xs)|“0”无
其中digit=toInteger(ord x-ord“0”)
MayberadInteger str=fmap(符号*)(MayberadUnsignedinteger str')
其中(符号,str')=拆分为符号和数字str
MayberadNum::(积分a,有界a)=>字符串->可能是a
MayberadNum=fmap fromInteger。
mfilter(\n->n>=toInteger(minBound::a)和
n可能是Int
Mayberadint=fmap fromInteger。
mfilter(\n->n>=toInteger(minBound::Int)和

n问题在于
minBound
的签名中的
a
maybeReadNum
的签名中的
a
不同。您可以通过启用
ScopedTypeVariables
来解决此问题:

{-# LANGUAGE ScopedTypeVariables #-}

-- We need to use forall explicitly, otherwise ScopedTypeVariables doesn't take effect.
maybeReadNum :: forall a. (Integral a, Bounded a) => String -> Maybe a
maybeReadNum = fmap fromInteger . 
               mfilter (\n -> n >= toInteger (minBound :: a) && 
                              n <= toInteger (maxBound :: a)) .
               maybeReadInteger
aType of
的定义如下:

asTypeOf :: a -> a -> a
asTypeOf = const
它只是
const
,具有更严格的类型符号。这可以用来断言两个表达式的类型应该相同,这有助于编译器推断正确的类型

在上面的代码中,
asTypeOf
用于断言
minBound'
应该与fromInteger的结果具有相同的类型,而fromInteger又必须等于
maybeReadNum
签名中的
a
。由此,编译器推断
minBound'
的类型为
a
。然后
maxBound'
也应该有相同的类型,因此它也会得到类型
a
。这有点困难,而且只使用
ScopedTypeVariables
可能更容易、更好,但是它可能是一种保持跨编译器可移植性的方法(如果您还没有使用某些扩展)

maybeReadNum :: (Integral a, Bounded a) => String -> Maybe a
maybeReadNum = fmap ((`asTypeOf` minBound') . fromInteger) . 
               mfilter (\n -> n >= toInteger minBound' && 
                              n <= toInteger maxBound') .    
               maybeReadInteger
  where minBound' = minBound
        maxBound' = maxBound `asTypeOf` minBound'
asTypeOf :: a -> a -> a
asTypeOf = const