下面的代碼會導致一條錯誤訊息,乍一看,似乎暗示 GHC 不理解型別族的定義WrapParams:
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
import GHC.TypeLits( Nat, type (-) )
import Data.Kind( Type )
newtype Wrapped a = Wrapped a
-- |
-- E.g., `WrapParams 2 (Int -> String -> Bool)` is `Wrapped Int -> Wrapped String -> Bool`
--
type family WrapParams (n :: Nat) (f :: Type) where
WrapParams 0 f = f
WrapParams n (p -> f) = Wrapped p -> WrapParams (n - 1) f
-- |
-- E.g., `extendToWrappedParams @2 ( ) (Wrapped 1) (wrapped 2)` is supposed to be 3.
--
class ExtendToWrappedParams (n :: Nat) (f :: Type) where
extendToWrappedParams :: f -> WrapParams n f
instance ExtendToWrappedParams 0 t where
extendToWrappedParams t = t
instance (ExtendToWrappedParams (n - 1) f) => ExtendToWrappedParams n (p -> f) where
extendToWrappedParams g = h
where
h (Wrapped p) = extendToWrappedParams @(n - 1) @f (g p)
這是錯誤(使用 GHC 8.10.7):
? Couldn't match expected type ‘WrapParams n (p -> f)’
with actual type ‘Wrapped p -> WrapParams (n - 1) f’
? In the expression: h
In an equation for ‘extendToWrappedParams’:
extendToWrappedParams g
= h
where
h (Wrapped p) = extendToWrappedParams @(n - 1) @f (g p)
In the instance declaration for ‘ExtendToWrappedParams n (p -> f)’
前兩行WrapParams逐字參考了定義,給人的印象是 GHC 不知何故不理解它。顯然,這不可能是實際發生的事情 - 那么,我錯過了什么?有什么方法(除了求助于unsafeCoerce)來編譯上面的代碼嗎?
uj5u.com熱心網友回復:
WrapParams n (p -> f)Wrapped p -> WrapParams (n - 1) f僅當nis not時才等于0。在 Haskell 中沒有直接的方式來表達不等式。通常的解決方法包括切換到 Peano naturals,或分支布爾比較 ( Data.Type.Equality.==) 而不是模式匹配,Nat因此您可以將其撰寫(n == 0) ~ 'False為約束。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/447869.html
