Haskell 将输出单子类型的函数转换为输出原始值类型的函数

Haskell 将输出单子类型的函数转换为输出原始值类型的函数,haskell,monads,Haskell,Monads,我有两个类型定义 type Mapper a k v = a -> [(k,v)] type MapperM m a k v = a -> m [(k,v)] 我想写一个函数,从类型转换一个值 (Ord k, Monad m) => MapperM m a k v 打字 Ord k => Mapper a k v 基本上是一个函数,它以a->m[(k,v)]作为参数,并返回a->[(k,v)]作为输出 我所有的尝试都以Haskell类型检查失败 我认为这在数学上是

我有两个类型定义

type Mapper a k v = a -> [(k,v)]
type MapperM m a k v = a -> m [(k,v)]
我想写一个函数,从类型转换一个值

(Ord k, Monad m) => MapperM m a k v
打字

Ord k => Mapper a k v 
基本上是一个函数,它以a->m[(k,v)]作为参数,并返回a->[(k,v)]作为输出


我所有的尝试都以Haskell类型检查失败

我认为这在数学上是不可能的

考虑m为Maybe时的情况:函数可以从[(k,v)]返回[(k,v)],但它会从零返回什么

如果monad是IO,那么从monad中提取参数将破坏IO提供的安全性


也考虑到你的函数必须为任何可想象的单元格工作。

< P>我相信它在数学上是不可能的。< /P> 考虑m为Maybe时的情况:函数可以从[(k,v)]返回[(k,v)],但它会从零返回什么

如果monad是IO,那么从monad中提取参数将破坏IO提供的安全性


也考虑到你的功能必须为任何可想象的单元格工作。< / P>也许对你有用?尤其是您不能这样做,因为对于任意单子

m
,通常不可能将
ma
转换为
a
。(这正是@lucidbrot链接的内容,但我认为在这里重申这一点可能会有用,这样你就不必遵循链接。)我的输出是否可能是(单子m)=>m映射器AKV-基本上用单子包装我不可能的原始期望输出?@GilShafriri,你的意思是
(Ord k,单子m)=>映射器m a k v->m(映射器a k v)
?这也是不可能的:您必须能够将函数
Monad m=>a->mb
转换为
Monad m=>m(a->b)
,这是无法完成的。(这一次,这是不可能的,因为
a->mb
中的任何一个一元副作用都可以依赖于
a
,而
m(a->b)
中的任何一个一元副作用都不能依赖于
a
)如果你有一个函数
Monad m=>a->m[(k,v)]
,你可以将其转换为
a->[(k,v)]
使用以下
convert=(runIdentity.)
(您可能必须从
Data.Functor.Identity导入)。当monad是一个特定的monad时,问题就出现了,在这种情况下,您不必转换。但是如果这个函数在任何monad上都是泛型的,那么你可以使用identity monad。也许对你有用?尤其是您不能这样做,因为对于任意单子
m
,通常不可能将
ma
转换为
a
。(这正是@lucidbrot链接的内容,但我认为在这里重申这一点可能会有用,这样你就不必遵循链接。)我的输出是否可能是(单子m)=>m映射器AKV-基本上用单子包装我不可能的原始期望输出?@GilShafriri,你的意思是
(Ord k,单子m)=>映射器m a k v->m(映射器a k v)
?这也是不可能的:您必须能够将函数
Monad m=>a->mb
转换为
Monad m=>m(a->b)
,这是无法完成的。(这一次,这是不可能的,因为
a->mb
中的任何一个一元副作用都可以依赖于
a
,而
m(a->b)
中的任何一个一元副作用都不能依赖于
a
)如果你有一个函数
Monad m=>a->m[(k,v)]
,你可以将其转换为
a->[(k,v)]
使用以下
convert=(runIdentity.)
(您可能必须从
Data.Functor.Identity导入)。当monad是一个特定的monad时,问题就出现了,在这种情况下,您不必转换。但是如果该函数在任何monad上都是泛型的,那么可以使用identity monad。