Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.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_Symbolic Math_Algebra - Fatal编程技术网

用Haskell表示交换半群多项式

用Haskell表示交换半群多项式,haskell,symbolic-math,algebra,Haskell,Symbolic Math,Algebra,我试图表达如下术语: a0 <> a1 <> ... <> an-1 newtype SemigroupPolynomial a = SP Map a Integer 其中,映射包含多项式的不同项及其计数 这样,我们就可以表示和 3 + 3 + 6 as(假设重载列表): 但我们也可以表示以下术语: 3 * 3 * 6 半群多项式可以是半群的一个实例: instance ??? a => Semigroup (SemigroupPolynomia

我试图表达如下术语:

a0 <> a1 <> ... <> an-1
newtype SemigroupPolynomial a = SP Map a Integer
其中,映射包含多项式的不同项及其计数

这样,我们就可以表示和

3 + 3 + 6
as(假设重载列表):

但我们也可以表示以下术语:

3 * 3 * 6
半群多项式
可以是
半群
的一个实例:

instance ??? a => Semigroup (SemigroupPolynomial a) where
    (MP p0) <> (MP p1) = 
        MP $ Map.filter (0/=) $ Map.unionWith (+) p0 p1
实例???a=>半群(半群多项式a),其中
(MP p0)(MP p1)=
MP$Map.filter(0/=)$Map.union带(+)p0 p1
否问题是我必须在
中设置哪些约束,以便:

  • 操作是可交换和关联的
  • 它可以用来表示总和和乘积,如上所示
    关于如何表示交换幺半群的类似问题。然而,似乎约束
    (阿贝尔m,幺半群m)
    可能太强了(我不需要零元素),这将阻止我使用它来表示产品。

    正如@LeftRoundout所评论的,这里不需要约束。不要被“约束”这个词所愚弄。在Haskell中,约束的主要目的不是以某种方式约束特定类型或操作的行为。相反,它是将函数将接受的类型集约束为支持一组操作的类型

    当我写作时:

    fmapTwice :: (Functor f) => (a -> a) -> f a -> f a
    fmapTwice f = fmap (f . f)
    
    我并不是真的限制类型
    f
    像一个函子一样工作,并遵守函子所要求的规则。相反,我将
    fmap两次
    函数限制为仅应用于支持
    fmap
    操作的类型
    f

    没有什么能阻止某个混蛋写作:

    data Foo a = Foo a | NoFoo deriving (Show)
    instance Functor Foo where
        fmap _ _ = NoFoo   -- invalid functor violates:  fmap id = id
    
    并将我的函数应用于此无效函子:

    > fmapTwice (*2) (Foo 10)
    NoFoo
    >
    
    Haskell依靠程序员规则来确保声明为具有
    Functor
    实例的东西是一个行为良好的Functor

    在您的示例中,实例:

    import Data.Semigroup
    import qualified Data.Map as Map
    import Data.Map.Strict (Map)
    
    data SemigroupPolynomial a = SP (Map a Integer) deriving (Show)
    instance (Ord a) => Semigroup (SemigroupPolynomial a) where
        (SP p0) <> (SP p1) = 
            SP $ Map.filter (0/=) $ Map.unionWith (+) p0 p1
    
    foldSP' :: (Monoid a) => SemigroupPolynomial a -> a
    foldSP' (SP m) = mconcat $ concatMap (\(a, n) -> replicate (fromIntegral n) a)
                                         (Map.assocs m)
    
    如果您想以某种方式在数据类型中引入可交换性要求,一种方法(根本不涉及Haskell“约束”)是编写如下内容:

    data CommutativeOp a = CO (a -> a -> a)
    foldSP :: CommutativeOp a -> SemigroupPolynomial a -> a
    foldSP (CO f) (SP m) = <same as above>
    
    您正在声明
    (+)
    (*)
    是交换操作,这将确保
    foldSP
    仅适用于此类操作:

    foldSP :: (a -> a -> a) -> SemigroupPolynomial a -> a
    foldSP f (SP m) = foldr1 f $ concatMap (\(a, n) -> replicate (fromIntegral n) a)
                                           (Map.assocs m)
    
    main = do let sp = singleton 3 <> singleton 3 <> singleton 6
              print sp
              print $ foldSP (*) sp
              print $ foldSP (+) sp
              print $ foldSP (-) sp   -- wrong, but it's your own damn fault
    
    main = do let sp = singleton 3 <> singleton 3 <> singleton 6
              print $ foldSP plusOp sp
              print $ foldSP timesOp sp
    
    现在fold操作将使用newtype中隐含的操作(这里,仅使用monoid实例):

    也许这就是你想要的。如果是,完整示例如下所示:

    import Data.Semigroup
    import qualified Data.Map as Map
    import Data.Map.Strict (Map)
    
    newtype SemigroupPolynomial a = SP (Map a Integer) deriving (Show)
    
    class Commutative a
    instance Commutative (Sum a)
    instance Commutative (Product a)
    instance (Ord a, Commutative a) => Semigroup (SemigroupPolynomial a) where
        (SP p0) <> (SP p1) = 
            SP $ Map.filter (0/=) $ Map.unionWith (+) p0 p1
    
    singleton :: a -> SemigroupPolynomial a
    singleton x = SP $ Map.singleton x 1
    
    foldSP' :: (Monoid a) => SemigroupPolynomial a -> a
    foldSP' (SP m) = mconcat $ concatMap (\(a, n) -> replicate (fromIntegral n) a)
                                         (Map.assocs m)
    
    main = do let sp1 = singleton (Sum 3) <> singleton (Sum 3) <> singleton (Sum 6)
              print sp1
              print (foldSP' sp1)
              let sp2 = singleton (Product 3) <> singleton (Product 3) 
                              <> singleton (Product 6)
              print sp2
              print (foldSP' sp2)
    
    导入数据半群
    导入符合条件的数据。映射为映射
    导入Data.Map.Strict(Map)
    新类型半群多项式a=SP(映射一个整数)派生(显示)
    类交换a
    实例交换(和a)
    实例交换(乘积a)
    实例(Ord a,交换a)=>半群(半群多项式a),其中
    (SP p0)(SP p1)=
    SP$Map.filter(0/=)$Map.union带(+)p0 p1
    单例::a->半群多项式a
    单例x=SP$Map.singleton x 1
    foldSP':(幺半群a)=>半群多项式a->a
    foldSP'(SP m)=mconcat$concatMap(\(a,n)->复制(从整数n)a)
    (Map.assocs m)
    main=do让sp1=singleton(Sum 3)singleton(Sum 3)singleton(Sum 6)
    打印sp1
    打印(foldSP的sp1)
    设sp2=singleton(产品3)singleton(产品3)
    单身人士(产品6)
    打印sp2
    打印(foldSP的sp2)
    
    正如@LeftRoundound所评论的,这里不需要约束。不要被“约束”这个词所愚弄。在Haskell中,约束的主要目的不是以某种方式约束特定类型或操作的行为。相反,它是将函数将接受的类型集约束为支持一组操作的类型

    当我写作时:

    fmapTwice :: (Functor f) => (a -> a) -> f a -> f a
    fmapTwice f = fmap (f . f)
    
    我并不是真的限制类型
    f
    像一个函子一样工作,并遵守函子所要求的规则。相反,我将
    fmap两次
    函数限制为仅应用于支持
    fmap
    操作的类型
    f

    没有什么能阻止某个混蛋写作:

    data Foo a = Foo a | NoFoo deriving (Show)
    instance Functor Foo where
        fmap _ _ = NoFoo   -- invalid functor violates:  fmap id = id
    
    并将我的函数应用于此无效函子:

    > fmapTwice (*2) (Foo 10)
    NoFoo
    >
    
    Haskell依靠程序员规则来确保声明为具有
    Functor
    实例的东西是一个行为良好的Functor

    在您的示例中,实例:

    import Data.Semigroup
    import qualified Data.Map as Map
    import Data.Map.Strict (Map)
    
    data SemigroupPolynomial a = SP (Map a Integer) deriving (Show)
    instance (Ord a) => Semigroup (SemigroupPolynomial a) where
        (SP p0) <> (SP p1) = 
            SP $ Map.filter (0/=) $ Map.unionWith (+) p0 p1
    
    foldSP' :: (Monoid a) => SemigroupPolynomial a -> a
    foldSP' (SP m) = mconcat $ concatMap (\(a, n) -> replicate (fromIntegral n) a)
                                         (Map.assocs m)
    
    如果您想以某种方式在数据类型中引入可交换性要求,一种方法(根本不涉及Haskell“约束”)是编写如下内容:

    data CommutativeOp a = CO (a -> a -> a)
    foldSP :: CommutativeOp a -> SemigroupPolynomial a -> a
    foldSP (CO f) (SP m) = <same as above>
    
    您正在声明
    (+)
    (*)
    是交换操作,这将确保
    foldSP
    仅适用于此类操作:

    foldSP :: (a -> a -> a) -> SemigroupPolynomial a -> a
    foldSP f (SP m) = foldr1 f $ concatMap (\(a, n) -> replicate (fromIntegral n) a)
                                           (Map.assocs m)
    
    main = do let sp = singleton 3 <> singleton 3 <> singleton 6
              print sp
              print $ foldSP (*) sp
              print $ foldSP (+) sp
              print $ foldSP (-) sp   -- wrong, but it's your own damn fault
    
    main = do let sp = singleton 3 <> singleton 3 <> singleton 6
              print $ foldSP plusOp sp
              print $ foldSP timesOp sp
    
    现在fold操作将使用newtype中隐含的操作(这里,仅使用monoid实例):

    也许这就是你想要的。如果是,完整示例如下所示:

    import Data.Semigroup
    import qualified Data.Map as Map
    import Data.Map.Strict (Map)
    
    newtype SemigroupPolynomial a = SP (Map a Integer) deriving (Show)
    
    class Commutative a
    instance Commutative (Sum a)
    instance Commutative (Product a)
    instance (Ord a, Commutative a) => Semigroup (SemigroupPolynomial a) where
        (SP p0) <> (SP p1) = 
            SP $ Map.filter (0/=) $ Map.unionWith (+) p0 p1
    
    singleton :: a -> SemigroupPolynomial a
    singleton x = SP $ Map.singleton x 1
    
    foldSP' :: (Monoid a) => SemigroupPolynomial a -> a
    foldSP' (SP m) = mconcat $ concatMap (\(a, n) -> replicate (fromIntegral n) a)
                                         (Map.assocs m)
    
    main = do let sp1 = singleton (Sum 3) <> singleton (Sum 3) <> singleton (Sum 6)
              print sp1
              print (foldSP' sp1)
              let sp2 = singleton (Product 3) <> singleton (Product 3) 
                              <> singleton (Product 6)
              print sp2
              print (foldSP' sp2)
    
    导入数据半群
    导入符合条件的数据。映射为映射
    导入Data.Map.Strict(Map)
    新类型半群多项式a=SP(映射一个整数)派生(显示)
    类交换a
    实例交换(和a)
    实例交换(乘积a)
    实例(Ord a,交换a)=>半群(半群多项式a),其中
    (SP p0)(SP p1)=
    SP$Map.filter(0/=)$Map.union带(+)p0 p1
    单例::a->半群多项式a
    单例x=SP$Map.singleton x 1
    foldSP':(幺半群a)=>半群多项式a->a
    foldSP'(SP m)=mconcat$concatMap(\(a,n)->复制(从整数n)a)
    (Map.assocs m)
    main=do让sp1=singleton(Sum 3)singleton(Sum 3)singleton(Sum 6)
    打印sp1
    打印(foldSP的sp1)
    设sp2=singleton(产品3)singleton(产品3)
    单身人士(产品6)
    打印sp2