haskell - Haskell 中的多态类型族实例
问题描述
我正在尝试编写代码来模拟随机变量,并且我希望使事物尽可能多态。这可能涉及使用类型族,这对我来说是全新的。
这是我的代码的简化版本:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
data TrivialDist a = Trivial a
getVal :: TrivialDist a -> a
getVal (Trivial x) = x
class JointDist d a where
toTrivialDist :: d a -> TrivialDist [a]
data TrivialJointDist a = TrivialJoint [a]
instance JointDist TrivialJointDist a where
toTrivialDist :: TrivialJointDist a -> TrivialDist [a]
toTrivialDist (TrivialJoint xs) = Trivial xs
class Simulable s a where
type Samp s a :: *
-- generates infinite stream of random samples from a distribution
samples :: s a -> IO [Samp s a]
-- generates a single random sample from a distribution
sample :: s a -> IO (Samp s a)
sample = fmap head . samples
instance Simulable TrivialDist a where
type Samp TrivialDist a = a
samples :: TrivialDist a -> IO [a]
samples (Trivial x) = return $ repeat x
instance (JointDist d a) => Simulable d a where
type Samp d a = [a]
samples :: d a -> IO [[a]]
samples = samples . toTrivialDist
当我将它加载到 ghci 中时,我收到此错误:
test.hs:30:10: error:
Conflicting family instance declarations:
Samp TrivialDist a = a -- Defined at test.hs:30:10
Samp d a = [a] -- Defined at test.hs:40:10
|
30 | type Samp TrivialDist a = a
| ^^^^^^^^^^^^^^^^^^^^^^
Failed, 0 modules loaded.
这个问题好像和这里发现的很像(解释好像是GHC不能根据约束来区分类型),但是没有提出解决方案。
如果我将最后一个实例声明更改为:
instance Simulable TrivialJointDist a where
type Samp TrivialJointDist a = [a]
samples :: TrivialJointDist a -> IO [[a]]
samples = samples . toTrivialDist
但是,这样我就失去了多态性的优势,因为我需要为JointDist d a
.
任何帮助深表感谢!
解决方案
在摸索了一下之后,我想我找到了一个使用等式约束而不是显式类型族的解决方案:
class Simulable s a b where
-- generates infinite stream of random samples from a distribution
samples :: s a -> IO [b]
-- generates a single random sample from a distribution
sample :: s a -> IO b
sample = fmap head . samples
instance (b ~ a) => Simulable TrivialDist a b where
samples :: TrivialDist a -> IO [a]
samples (Trivial x) = return $ repeat x
instance {-# OVERLAPPABLE #-} (JointDist d a, b ~ [a]) => Simulable d a b where
samples :: d a -> IO [[a]]
samples = samples . toTrivialDist
{-# OVERLAPPABLE #-}
pragma 指示 GHC 允许实例与TrivialDist a b
实例重叠d a b
(否则我们会得到错误)。
推荐阅读
- python - TensorFlow 给出“
不是此图的元素”从另一个类调用时出错 - sql - 一旦在查询中输入,如何使记录只读?
- php - remove_action wc_empty_cart_message 在 WooCommerce 中不起作用
- d3.js - D3如何修复树形图中没有根?
- woocommerce - 报告中的“客户”栏是否可以轻松更改为“公司名称”?
- jekyll - Liquid - 有条件地包含来自 _includes 文件夹的文件
- google-cloud-platform - BigQuery - JSONpath 递归运算符 (1/2)
- spring - Springfox 3.0 在 Spring 框架中不起作用
- java - Jenkins - 无法执行目标 org.apache.maven.plugins:maven-compiler-plugin:3.1:compile on project
- reactjs - 上下文给了我未定义的