将类型变量约束为具体类型

Eri*_*ikR 2 polymorphism haskell type-variables

我有这个单形代码:

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

一个完全多态的签名push是:

push :: (MArray a e m, Ix e, Num e)  => a e e -> e -> [e] -> m e
Run Code Online (Sandbox Code Playgroud)

但我试着写这些部分多态签名:

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

我得到的错误就像can't deduce (e ~ Int),can't deduce (MArray a Int m) ...Non type-variable argument in constraint,Illegal equational constraint

有没有办法e将第一个签名中的类型变量约束为具体类型Int

GS *_*ica 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
Run Code Online (Sandbox Code Playgroud)

在Haskell Prime wiki上有一些关于此扩展讨论.

第四个签名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
Run Code Online (Sandbox Code Playgroud)

在这种特殊情况下,我认为它对调用上下文的类型检查具有与其他工作签名完全相同的效果FlexibleContexts,但通常具有等式约束的类型变量与具有具体类型的不完全相同.