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