在Haskell中,如何强制表达式为函数的返回类型?

Dre*_*rew 1 polymorphism haskell types integer

我想概括这个函数,(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
Run Code Online (Sandbox Code Playgroud)

Zet*_*eta 5

基本上,您希望在函数中的某个位置使用类型参数.这正是范围类型变量的用途:

{-# 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
Run Code Online (Sandbox Code Playgroud)

或者你可以使用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
Run Code Online (Sandbox Code Playgroud)

asTypeOf是一个相当简单的函数,但它的类型确保remaindermaxBound具有相同的类型:

asTypeOf :: a -> a -> a
asTypeOf = const
Run Code Online (Sandbox Code Playgroud)