Joh*_*ler 7 polymorphism haskell pattern-matching
以下代码旨在生成Double或Integer.s被假定为negate或id; n整个部分; 和f小数部分或Nothing整数.
computeValue :: Num a => (a->a) -> Integer -> (Maybe Double) -> Either Double Integer
computeValue s n Nothing = Right $ s n
computeValue s n (Just a) = Left $ s (fromIntegral n + a)
Run Code Online (Sandbox Code Playgroud)
当我编译这个时,我得到:
test1.hs:2:28:
Couldn't match type `Integer' with `Double'
Expected type: Either Double Integer
Actual type: Either Double a
In the expression: Right $ s n
In an equation for `computeValue':
computeValue s n Nothing = Right $ s n
test1.hs:2:38:
Couldn't match type `Integer' with `Double'
In the first argument of `s', namely `n'
In the second argument of `($)', namely `s n'
In the expression: Right $ s n
Run Code Online (Sandbox Code Playgroud)
似乎某种程度上编译器已经忘记了s多态的事实.这里发生了什么,我该如何解决?
lef*_*out 10
s从函数内部不是多态的:你可以使用任何在某个 Num实例上起作用的函数作为这个参数,它可能是一个只能工作的函数Complex!你需要的是一个普遍量化的函数s,即可以用任何 Num实例实际调用的函数.
{-# LANGUAGE Rank2Types #-}
computeValue :: (forall a . Num a => a->a) -> Integer -> Maybe Double -> Either Double Integer
computeValue s n Nothing = Right $ s n
computeValue s n (Just a) = Left $ s (fromIntegral n + a)
Run Code Online (Sandbox Code Playgroud)
这适用于:
Prelude Data.Either> computeValue id 3 Nothing
Right 3
Prelude Data.Either> computeValue negate 57 (Just pi)
Left (-60.1415926535898)
Run Code Online (Sandbox Code Playgroud)