haskell - RankNTypes 与返回类型不匹配

标签 haskell higher-rank-types

使用RankNTypes,我定义了一个不依赖于类型变量的类型。这是解决下面案例的正确方法吗?

我需要定义一些在 ST 中使用的函数,当然,这些函数不依赖于 s。然而,这会导致一个问题,即应用了两个 IntExp 表达式不会产生 Block。为什么?

这是一个复制器:

import Control.Monad.ST
import Data.Vector.Unboxed (Vector)
import qualified Data.Vector.Unboxed as U
import Data.Vector.Unboxed.Mutable (STVector)
import qualified Data.Vector.Unboxed.Mutable as UM

type Exp = Int -> Int -> Block
type Block = forall s . STVector s Int -> ST s Int

block :: [Block] -> Block
block [] _ = return 0  -- mapM doesn't work, either - ok, I kinda see why
block (e:es) a = do x <- e a
                    xs <- block es a
                    return $ x+xs

copy :: Exp
copy i j a = do
        aj <- a `UM.unsafeRead` j
        UM.unsafeWrite a i aj
        return 1


f :: Block -> Vector Int -> Int
f blk ua = runST $ U.thaw ua >>= blk

g :: Block -> Int
g blk = f blk $ U.fromListN 12 [1..]

main = print . g $ block [copy 10 1]

我在最后一行得到的错误:

Couldn't match type `STVector s0 Int -> ST s0 Int'
              with `forall s. STVector s Int -> ST s Int'
Expected type: Block
  Actual type: STVector s0 Int -> ST s0 Int
In the return type of a call of `block'
Probable cause: `block' is applied to too few arguments
In the second argument of `($)', namely `block [copy 10 1]'
In the expression: print . g $ block [copy 10 1]

据我所知,预期类型和实际类型之间的差异在于 forall s. 位。

最佳答案

虽然我更喜欢 @Oleg 发布的解决方案,但我想分享一个替代方案。

替换

main = print . g $ block [copy 10 1]

main = print (g (block [copy 10 1]))

原因:谓语类型使编译器很难猜测上面的 (.)($) 的类型。

另一种选择是用实例化类型来注释 (.)($) ——但这会相当麻烦。

关于haskell - RankNTypes 与返回类型不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27942828/

相关文章:

haskell - 在没有 unsafeCoerce 的情况下玩弄存在主义

sockets - Haskell与操作系统进行交互(中断)

Haskell根据字段名称字符串动态设置记录字段?

haskell - rank-3(或更高)多态性的用例?

haskell - let 如何与 Haskell 中更高级别的类型交互?

haskell - RankNTypes 和教堂数字

haskell - 什么是 '[] and ' : in Haskell?

haskell - monad 中的 FoldlWithKey

javascript - RxJS.Observable 是单子(monad)吗?

haskell - 实例声明的RankNTypes?