【问题标题】:How can I move this instance method definition to class default?如何将此实例方法定义移动到类默认值?
【发布时间】:2019-01-01 07:51:31
【问题描述】:

考虑这个类和一个示例实例。

目的是提供一个类型级别开关,允许将基本类型(在本例中为Int)转换为经过验证的谓词子类型,以供将来使用。当然,这个类有点做作,但我是从实际代码中提取出来的,我会用更有用的方法填充它,除非我卡住了。

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeFamilyDependencies #-}
{-# LANGUAGE TypeApplications #-}

module Collection where

import Data.Tagged

-- $setup
--
-- λ :set -XTypeApplications

class Collected phantom
  where
    type Element phantom = r | r -> phantom
    type Element phantom = Tagged phantom Int

    type Collection phantom = r | r -> phantom
    type Collection phantom = Tagged phantom [Int]

    collection :: Collection phantom

    inCollection :: Int -> Maybe (Element phantom)

data Primes

instance Collected Primes
  where
    type Element Primes = Tagged Primes Int
    type Collection Primes = Tagged Primes [Int]

    collection = Tagged [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]

    -- inCollection :: Int -> Maybe (Element Primes)
    inCollection element
        | element `elem` unTagged (collection @Primes) = Just $ Tagged element
        | otherwise = Nothing

-- ^
-- λ inCollection @Primes 7
-- Just (Tagged 7)
-- λ inCollection @Primes 8
-- Nothing

(这是一个可运行的代码,其中包含通过的 repl 测试。)

我将处理同一基本类型上的几个子类型,它们仅在collection 的定义上有所不同,而证明方法是一致查找。因此,没有理由没有该方法的默认代码。但是,我无法设计出这样的代码。我的第一个草稿无法进行类型检查,而第二个经过调整的草稿运行,但似乎没有终止。

这是初稿:

...
{-# LANGUAGE DefaultSignatures #-}
...

class Collected phantom
...
    inCollection :: Int -> Maybe (Element phantom)
    default inCollection :: ( Element phantom    ~ Tagged phantom  Int
                            , Collection phantom ~ Tagged phantom [Int] )
                         => Int -> Maybe (Element phantom)
    inCollection element
        | element `elem` unTagged collection = Just $ Tagged element
        | otherwise = Nothing
...

这是第二个:

...
{-# LANGUAGE ScopedTypeVariables #-}
...

class Collected phantom
...
    inCollection :: ...
    default inCollection :: ...
    inCollection ...
      where
        collection = (collection :: Collection phantom)

(仅显示添加的部分。实例中的相应方法定义已被删除。在第二稿中,除了 pragma 之外唯一添加的是尝试键入 collection 的最后一行。)

 

有什么问题?可以做什么?

【问题讨论】:

    标签: haskell types type-families


    【解决方案1】:

    看来以下将起作用。这个想法是在默认的正确类型(使用collection @phantom)中实例化collection,这也需要ScopedTypeVariables

    更新:我现在知道这是您在第二次尝试时尝试所做的。问题是您的 where 子句定义了一个无限循环,因为 RHS 上的 collection 与 LHS 上绑定的 collection 相同(根据需要插入 facepalm)。

    {-# LANGUAGE DefaultSignatures #-}
    {-# LANGUAGE ScopedTypeVariables #-}
    {-# LANGUAGE TypeFamilies #-}
    {-# LANGUAGE TypeFamilyDependencies #-}
    {-# LANGUAGE TypeApplications #-}
    
    module Collection where
    
    import Data.Tagged
    
    class Collected phantom
      where
        type Element phantom = r | r -> phantom
        type Element phantom = Tagged phantom Int
    
        type Collection phantom = r | r -> phantom
        type Collection phantom = Tagged phantom [Int]
    
        collection :: Collection phantom
    
        inCollection :: Int -> Maybe (Element phantom)
        default inCollection :: ( Collection phantom ~ Tagged phantom [Int]
                                , Element phantom ~ Tagged phantom Int)
                                => Int -> Maybe (Element phantom)
        inCollection element
            | element `elem` unTagged (collection @phantom) = Just $ Tagged element
            | otherwise = Nothing
    
    data Primes
    
    instance Collected Primes
      where
        type Element Primes = Tagged Primes Int
        type Collection Primes = Tagged Primes [Int]
    
        collection = Tagged [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-18
      • 2012-11-11
      • 1970-01-01
      • 2012-06-11
      • 1970-01-01
      • 2011-12-29
      相关资源
      最近更新 更多