我有这个单形代码:
import Data.Array.MArray
import Data.Array.IO (IOUArray)
import Data.Ix (Ix)
push :: IOUArray Int Int -> Int -> [Int] -> IO Int
push stack top [] = return top
push stack top (k:ks) = do
v <- readArray stack k
if v >= 0 then push stack top ks
else do writeArray stack k top
push stack k ks
push
的完全多态签名将是:
push :: (MArray a e m, Ix e, Num e) => a e e -> e -> [e] -> m e
但我试着写下这些部分多态签名:
push :: MArray a e m => a Int e -> Int -> [Int] -> m Int
push :: MArray a e m => a Int Int -> Int -> [Int] -> m Int
push :: MArray a Int m => a Int Int -> Int -> [Int] -> m Int
push :: (MArray a e m, e ~ Int) => a e e -> e -> [e] -> m e
我收到的错误有can't deduce (e ~ Int)
,can't deduce (MArray a Int m) ...
和Non type-variable argument in constraint
,Illegal equational constraint
有没有办法将第一个签名中的类型变量e
约束为Int
这样的具体类型?
答案 0 :(得分:5)
如果您启用FlexibleContexts
(如错误所示),则第三个签名有效:
{-# LANGUAGE FlexibleContexts #-}
import Data.Array.MArray
import Data.Array.IO (IOUArray)
import Data.Ix (Ix)
push :: MArray a Int m => a Int Int -> Int -> [Int] -> m Int
-- push :: IOUArray Int Int -> Int -> [Int] -> IO Int
push stack top [] = return top
push stack top (k:ks) = do
v <- readArray stack k
if v >= 0 then push stack top ks
else do writeArray stack k top
push stack k ks
Haskell Prime wiki上有some discussion of this extension。
第四个签名与TypeFamilies
一起使用以允许e ~ Int
约束:
{-# LANGUAGE TypeFamilies #-}
import Data.Array.MArray
import Data.Array.IO (IOUArray)
import Data.Ix (Ix)
push :: (MArray a e m, e ~ Int) => a e e -> e -> [e] -> m e
-- push :: IOUArray Int Int -> Int -> [Int] -> IO Int
push stack top [] = return top
push stack top (k:ks) = do
v <- readArray stack k
if v >= 0 then push stack top ks
else do writeArray stack k top
push stack k ks
在这种特殊情况下,我认为它对调用上下文的类型检查与FlexibleContexts
的其他工作签名具有完全相同的效果,但通常具有等式约束的类型变量与具体的类型。
答案 1 :(得分:3)
第一个签名
push :: MArray a e m => a Int e -> Int -> [Int] -> m Int
不起作用,因为您正在读取类型为v <- readArray stack k
的数组元素e
,但是将其与0进行比较,即Int
或Integer
(编辑:真的任何Num
)。
第二个签名
push :: MArray a e m => a Int Int -> Int -> [Int] -> m Int
不起作用是因为您说a e m
是MArray
的实例,但后来尝试使用 a Int Int
。 GHC尝试使用给定约束统一所需约束,因此它尝试将e
与Int
匹配。
Ganesh的回答解决了其他两个签名。