简体   繁体   English

haskell - 如何避免这种无限类型? (相关数据和StateT)

[英]haskell — How to avoid this infinite type? (Associated data and StateT)

I want to set the type of the state parameter, of a state monad tranformer, to an associated type of that monad transformer. 我想将状态参数(状态monad转换器)的类型设置为该monad转换器的关联类型。 However, this results in constructing an infinite type, 但是,这导致构造无限类型,

s = AssocTyp (StateT s m) a

The intuition as to why this isn't really a problem is that, 关于为什么这不是一个真正的问题的直觉是,

AssocTyp (StateT s m) a = AssocTyp (StateT s' m) a

for all s and s' . 对于所有的ss' However, the compiler isn't smart enough to figure this out. 但是,编译器不够聪明,无法解决这个问题。 I've read that in some cases, a newtype can be used to avoid infinite types; 我读过在某些情况下,可以使用newtype来避免无限类型; how do I do it? 我该怎么做?

Here's minimized code to reproduce the question, 这是重现问题的最小化代码,

{-# LANGUAGE KindSignatures, TypeFamilies #-}

import Control.Monad.Trans.State

class MyMonad (m :: * -> *) where
    data AssocTyp m :: * -> *

instance MyMonad m => MyMonad (StateT s m) where
    data AssocTyp (StateT s m) a = StateTA (AssocTyp m a)

isAssocTyp :: Monad m => (AssocTyp m a) -> m ()
isAssocTyp x = return ()

x = do
    v <- get
    isAssocTyp (v)

I'm not sure what you're trying to achieve. 我不确定你想要实现的目标。 However, the equality you state, 但是,你所说的平等,

AssocTyp (StateT s m) a = AssocTyp (StateT s' m) a

is not true, because you are using a data family rather than a type family. 不是这样,因为您使用的是数据系列而不是类型系列。 The following code compiles: 以下代码编译:

{-# LANGUAGE KindSignatures, TypeFamilies #-}

import Control.Monad.Trans.State

class MyMonad (m :: * -> *) where
    type AssocTyp m :: * -> *

instance MyMonad m => MyMonad (StateT s m) where
    type AssocTyp (StateT s m) = AssocTyp m

isAssocTyp :: Monad m => (AssocTyp m a) -> m ()
isAssocTyp x = return ()

x :: Monad m => StateT (AssocTyp m a) m ()
x = do
    v <- get
    isAssocTyp v

The difference between type families and data families is that data families are injective , which means the following implication holds if DF is data family: 类型族和数据族之间的区别在于数据族是单射的 ,这意味着如果DF是数据族,则以下含义成立:

DF a b c = DF a' b' c'   =====>     a = a',   b = b',   c = c'

This is not what you want in your case. 这不是你想要的。

Just in case a data family is what you want, I have a variant that does type check: 如果数据系列是你想要的,我有一个类型检查的变体:

isAssocType' :: (Monad m1, Monad m0) => (AssocTyp m1 a) -> m0 ()
isAssocType' _ = return ()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM