专门针对Haskell中特殊类型类的monad绑定 [英] Specializing bind for monads over special typeclasses in Haskell

查看:101
本文介绍了专门针对Haskell中特殊类型类的monad绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在第二章最后一章少数单子更多非常好的教程学习你一个好的Haskell作者定义了以下单子:

  import Data.Ratio 
newtype Prob a = Prob {getProb :: [(a,Rational)]}派生Show
flatten :: Prob(Prob a) - > Prob a
flatten(Prob xs)= Prob $ concat $ map multAll xs
其中multAll(Prob innerxs,p)= map(\(x,r) - >(x,p * r ))innerxs
实例Monad Prob其中
return x = Prob [(x,1%1)]
m>> = f = flatten(fmap fm)
fail _ = Prob []

我想知道是否有可能在Haskell中专门化绑定运算符>> = 如果monad中的值属于像Eq这样的特殊类型类型,因为我希望将属于相同值的所有概率加起来。 解决方案

ConstraintKinds,TypeFamilies,KindSignatures,FlexibleContexts,UndecidableInstances# - }
module Control.Restricted(RFunctor(..),
RApplicative(..),
RMonad(..),
RMonadPlus(..),)其中
导入Prelude h í(Functor(..),Monad(..))
import Data.Foldable(Foldable(foldMap))
import GHC.Exts(Constraint)

class RFunctor f其中
类型限制fa :: Constraint
fmap ::(Restriction fa,Restriction fb)=> (a - > b) - > f a - > f b

class(RFunctor f)=>其中
pure ::(Restriction f a)=> a - > f a
(*)::(限制f a,限制f b)=> f(a - > b) - > f a - > f b

class(RApplicative m)=> RMonad m其中
(>> =)::(Restriction m a,Restriction m b)=> m a - > (a - > m b) - > m b
(>>)::(Restriction m a,Restriction m b)=> m a - > m b - > m b
a>> b = a>> = \ _ - > b
join ::(Restriction m a,Restriction m(m a))=> m(m a) - > m a
join a = a>> = id
fail ::(Restriction m a)=>字符串 - > m a
fail =错误

return ::(RMonad m,Restriction m a)=> a - > m a
return = pure

class(RMonad m)=> RMonadPlus m其中
mplus ::(Restriction m a)=> m a - > m a - > m a
mzero ::(Restriction m a)=> m a
msum ::(限制m a,可折叠t)=> t(m a) - > ma
msum t = getRMonadPlusMonoid $ foldMap RMonadPlusMonoid t

data RMonadPlusMonoid ma = RMonadPlusMonoid {getRMonadPlusMonoid :: ma}

instance(RMonadPlus m,Restriction ma)=> ; Monoid(RMonadPlusMonoid m a)其中
mappend(RMonadPlusMonoid x)(RMonadPlusMonoid y)= RMonadPlusMonoid $ mplus x y
mempty = RMonadPlusMonoid mzero
mconcat t = RMonadPlusMonoid。 msum $ map getRMonadPlusMonoid t

guard ::(RMonadPlus m,Restriction m a)=>布尔 - > m()
guard p = if p then return()else mzero

要使用限制monad,你需要像这样开始你的文件:

  { - #LANGUAGE Con​​straintKinds,TypeFamilies,RebindableSyntax# - } 
module { - module line - } where
import Prelude hiding(Functor(..),Monad(..))
import Control.Restricted


In the second last chapter For a Few Monads More of the very nice tutorial "Learn You a Haskell for a Great Good" the author defines the following monad:

import Data.Ratio  
newtype Prob a = Prob { getProb :: [(a,Rational)] } deriving Show
flatten :: Prob (Prob a) -> Prob a  
flatten (Prob xs) = Prob $ concat $ map multAll xs  
  where multAll (Prob innerxs,p) = map (\(x,r) -> (x,p*r)) innerxs
instance Monad Prob where  
  return x = Prob [(x,1%1)]  
  m >>= f = flatten (fmap f m)  
  fail _ = Prob []

I wondered if it is possible in Haskell to specialize the bind operator ">>=" in case the value in the monad belongs to a special typeclass like Eq, as I'd like to add up all probabilities belonging to the same value.

解决方案

This is called a "restricted monad" and you define it like this:

{-# LANGUAGE ConstraintKinds, TypeFamilies, KindSignatures, FlexibleContexts, UndecidableInstances #-}
module Control.Restricted (RFunctor(..),
                           RApplicative(..),
                           RMonad(..),
                           RMonadPlus(..),) where
import Prelude hiding (Functor(..), Monad(..))
import Data.Foldable (Foldable(foldMap))
import GHC.Exts (Constraint)

class RFunctor f where
    type Restriction f a :: Constraint
    fmap :: (Restriction f a, Restriction f b) => (a -> b) -> f a -> f b

class (RFunctor f) => RApplicative f where
    pure :: (Restriction f a) => a -> f a
    (<*>) :: (Restriction f a, Restriction f b) => f (a -> b) -> f a -> f b

class (RApplicative m) => RMonad m where
    (>>=) :: (Restriction m a, Restriction m b) => m a -> (a -> m b) -> m b
    (>>) :: (Restriction m a, Restriction m b)  => m a -> m b ->  m b
    a >> b = a >>= \_ -> b
    join :: (Restriction m a, Restriction m (m a)) => m (m a) -> m a
    join a = a >>= id
    fail :: (Restriction m a) => String -> m a
    fail = error

return :: (RMonad m, Restriction m a) => a -> m a
return = pure

class (RMonad m) => RMonadPlus m where
    mplus :: (Restriction m a) => m a -> m a -> m a
    mzero :: (Restriction m a) => m a
    msum :: (Restriction m a, Foldable t) => t (m a) -> m a
    msum t = getRMonadPlusMonoid $ foldMap RMonadPlusMonoid t

data RMonadPlusMonoid m a = RMonadPlusMonoid { getRMonadPlusMonoid :: m a }

instance (RMonadPlus m, Restriction m a) => Monoid (RMonadPlusMonoid m a) where
    mappend (RMonadPlusMonoid x) (RMonadPlusMonoid y) = RMonadPlusMonoid $ mplus x y
    mempty = RMonadPlusMonoid mzero
    mconcat t = RMonadPlusMonoid . msum $ map getRMonadPlusMonoid t

guard :: (RMonadPlus m, Restriction m a) => Bool -> m ()
guard p = if p then return () else mzero

To use a restricted monad, you need to begin your file like this:

{-# LANGUAGE ConstraintKinds, TypeFamilies, RebindableSyntax #-}
module {- module line -} where
import Prelude hiding (Functor(..), Monad(..))
import Control.Restricted

这篇关于专门针对Haskell中特殊类型类的monad绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆