Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 自由单子和类型约束_Haskell_Polymorphism_Constraints_Typeclass - Fatal编程技术网

Haskell 自由单子和类型约束

Haskell 自由单子和类型约束,haskell,polymorphism,constraints,typeclass,Haskell,Polymorphism,Constraints,Typeclass,我正在寻找处理haskell约束的实用策略或技巧,如下例所示 我有一个函子Choice,我想把解释器从Choice x函子转换成mx,把解释器从Free-Choice x转换成mx -- Choice : endofunctor data Choice next = Choice next next deriving (Show) instance Functor Choice where fmap f (Choice a b) = Choice (f a) (f b) -- I

我正在寻找处理haskell约束的实用策略或技巧,如下例所示


我有一个函子
Choice
,我想把解释器从
Choice x
函子转换成
mx
,把解释器从
Free-Choice x
转换成
mx

-- Choice : endofunctor  
data Choice next = Choice next next deriving (Show)
instance Functor Choice where 
   fmap f (Choice a b) = Choice (f a) (f b)

-- I have a function from the functor to a monad m
inter1 :: Choice x -> IO x
inter1 (Choice a b) = do 
  x <- readLn :: IO Bool 
  return $ if x then a else b

-- universal property gives me a function from the free monad to m 
go1 :: Free Choice x -> IO x
go1 = interpMonad inter1
然后它找不到要在interp2中应用的显示约束

我怀疑量词是问题所在,所以我简化为

lifting :: (forall x . x -> b) ->
           (forall x.  x -> b)
lifting = id

lifting2 :: (forall x . Show x => x -> b) ->
            (forall x . Show x => x -> b)
lifting2 = id


somefunction :: Show x => x -> String
somefunction = lifting show    -- FAILS

somefunction2 :: Show x => x -> String
somefunction2 = lifting2 show  -- OK
这突出了一个问题:
无法从上下文(Show x)中使用“Show”来推断(Show x1)
我们有两个不同的类型变量,约束不会从一个流向另一个


我可以编写一些专门的函数来处理以下约束(顺便说一句,不起作用),但我的问题是,处理这个问题的实用策略是什么?(相当于未定义,查看类型,继续…)


编辑

根据提供的答案,这里是对提升功能的修改

lifting :: forall b c. Proxy c
           ->  (forall x . c x => x -> b)
           ->  (forall x . c x => x -> b)
lifting _ = id


somefunction3 :: Show x => x -> String
somefunction3 = lifting (Proxy :: Proxy Show) show

我看不到您的intermonad函数,因此我将在这里包括一个可能的定义:

interpMonad :: forall f m x . (Functor f, Monad m) 
            => (forall y . f y -> m y) -> Free f x -> m x 
interpMonad xx = go . runIdentity . runFreeT  where 
  go (FreeF x) = xx x >>= go . runIdentity . runFreeT
  go (Pure  x) = return x 
为了在内部函数上也有类约束,只需将约束添加到内部函数。您还需要对类型
Free
进行正确的约束,并且需要额外的
代理来帮助类型检查器进行检查。否则,函数的定义相同:

interpMonadC :: forall f m x c . (Functor f, Monad m, c (Free f x)) 
             => Proxy c 
             -> (forall y . c y => f y -> m y) 
             -> (Free f x -> m x) 
interpMonadC _ xx = go . runIdentity . runFreeT  where 
  go (FreeF x) = xx x >>= go . runIdentity . runFreeT
  go (Pure  x) = return x 
现在很简单:

>:t interpMonadC (Proxy :: Proxy Show) interp2
interpMonadC (Proxy :: Proxy Show) interp2
  :: Show x => Free Choice x -> IO x

因此,通过在调用站点使用代理,我们传递了一个值,我们选择该值的类型为
proxy Show
,因此
c
类型变量为
Show
,该类型用作约束(通过ConstraintTypes选项)。在结果函数和内部函数中使用了相同的约束,这导致编译器在interp2上查找show实例,它很容易在上下文中找到该实例。。。。我能理解这些东西,但我想知道我写它们有多容易是不是
interpMonad
a
retract
?@arrowd:我忘了retract是什么。但是interMonad采用了一种自然转换interp2(为所有类型x统一定义,显然从
选择a
选择b
然后传输到
IO b
的功能与从
选择a
IO a
然后传输到
IO b
的功能相同)到另一个自然转变。interp2是内函子范畴中的一个箭头,从作为函子的
Choice
m
,自由/健忘附加项最初为您提供了一个唯一的箭头Intermonad,从作为函子的monad
free Choice
m
monad@arrowd这是同构Endo(F,U(m))/Endo的一个方向(自由F,m)。对于函子类别,内部更正:“一个唯一的箭头interpMonad'=>”一个唯一的箭头
interpMonad interp2
”above@nicolas我一直将约束视为子集。即
forall(x:x)。cx=>Proxy x
表示满足谓词
C
x
的子集。
interpMonad :: forall f m x . (Functor f, Monad m) 
            => (forall y . f y -> m y) -> Free f x -> m x 
interpMonad xx = go . runIdentity . runFreeT  where 
  go (FreeF x) = xx x >>= go . runIdentity . runFreeT
  go (Pure  x) = return x 
interpMonadC :: forall f m x c . (Functor f, Monad m, c (Free f x)) 
             => Proxy c 
             -> (forall y . c y => f y -> m y) 
             -> (Free f x -> m x) 
interpMonadC _ xx = go . runIdentity . runFreeT  where 
  go (FreeF x) = xx x >>= go . runIdentity . runFreeT
  go (Pure  x) = return x 
>:t interpMonadC (Proxy :: Proxy Show) interp2
interpMonadC (Proxy :: Proxy Show) interp2
  :: Show x => Free Choice x -> IO x