我想将此函数概括为(Integral a, Integral b, Bounded b) => a -> [b]
,但我不知道如何强制maxBound
获得结果的类型。这可能吗?
go :: Integral a => a -> Maybe (Word8, a)
go 0 = Nothing
go x
| x < 0 = error "Negative numbers are not acceptable"
| otherwise = Just $ (remainder, quotient)
where
quotient = fromInteger $ (toInteger x) `div` (toInteger (maxBound :: Word8))
remainder = fromInteger $ (toInteger x) `mod` (toInteger (maxBound :: Word8))
int2WordList :: Integral a => a -> [Word8]
int2WordList x = unfoldr go x
答案 0 :(得分:5)
基本上,您希望在函数中的某个位置使用类型参数。这正是scoped type variables的用途:
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Word
import Data.List
go :: forall a b. (Integral a, Integral b, Bounded b) => a -> Maybe (b, a)
go 0 = Nothing
go x
| x < 0 = error "Negative numbers are not acceptable"
| otherwise = Just $ (remainder, quotient)
where
quotient = fromInteger $ (toInteger x) `div` (toInteger (maxBound :: b))
remainder = fromInteger $ (toInteger x) `mod` (toInteger (maxBound :: b))
-- ^
-- that's the same `b` as above
int2List :: (Integral a, Integral b, Bounded b) => a -> [b]
int2List x = unfoldr go x
或者,您可以使用asTypeOf
:
go :: (Integral a, Integral b, Bounded b) => a -> Maybe (b, a)
go 0 = Nothing
go x
| x < 0 = error "Negative numbers are not acceptable"
| otherwise = Just $ (remainder, quotient)
where
quotient = fromInteger $ (toInteger x) `div` (toInteger (maxBound `asTypeOf` remainder))
remainder = fromInteger $ (toInteger x) `mod` (toInteger (maxBound `asTypeOf` remainder))
int2List :: (Integral a, Integral b, Bounded b) => a -> [b]
int2List x = unfoldr go x
asTypeOf
是一个相当简单的函数,但其类型确保remainder
和maxBound
具有相同的类型:
asTypeOf :: a -> a -> a
asTypeOf = const
答案 1 :(得分:3)
Haskell 98解决此问题的方法是asTypeOf
函数,例如:
quotient = fromInteger $ (toInteger x) `div` (toInteger (maxBound `asTypeOf` remainder))
我建议稍微重新处理你的表达式:
xInt = toInteger x
mbound = toInteger (maxBound `asTypeOf` remainder)
quotient = fromInteger $ xInt `div` mbound
remainder = fromInteger $ xInt `div` mbound
这将使您更清楚地想要将x
除以相同的值,然后将结果四舍五入为两种不同的类型。