新的GHC8和隐含参数

时间:2017-11-05 20:33:17

标签: haskell typeclass implicit

在他的implicit configuration paper中,Oleg反映了类型级别的值。

使用GHC8的新工具,他的演示可以改进什么? 例如,我们可以删除使用类型应用程序的undefined,但还有什么?

以下是介绍后的原文

{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE StandaloneDeriving #-}
#!/usr/bin/env stack
-- stack --resolver lts-9.2 script --package http-conduit --package tagged --package lens
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE ExplicitForAll      #-}
{-# OPTIONS_GHC -fno-warn-unused-imports -fno-warn-unused-local-binds  -fno-warn-missing-signatures #-}

import Prelude
import Control.Lens.Operators ((<&>))
import Data.Function
import Data.Kind

代码

-- Original
--------------
data Zero; data Twice (s :: Type); data Succ (s :: Type); data Pred (s :: Type) -- pure type

class ReflectNum1 s where reflectNum1 :: Num a => s -> a

instance ReflectNum1 Zero      where reflectNum1 _ = 0 -- on ne se sert pas de s
instance ReflectNum1 s => ReflectNum1 (Twice s) where reflectNum1 _ = (reflectNum1 (undefined :: s) * 2)
instance ReflectNum1 s => ReflectNum1 (Succ s ) where reflectNum1 _ = (reflectNum1 (undefined :: s) + 1)
instance ReflectNum1 s => ReflectNum1 (Pred s ) where reflectNum1 _ = (reflectNum1 (undefined :: s) - 1)

--
v1 :: Int = reflectNum1 (undefined :: Zero)

使用类型应用程序,我们可以很好地清理未定义的

--- Type Application

-- outillage
newtype Tagged s a = Tagged { unTag :: a } deriving Show
deriving instance Functor (Tagged s)
instance Applicative (Tagged s) where
  pure = Tagged
  Tagged f <*> Tagged x = Tagged (f x)
  _ *> n = n

retag :: Tagged s b -> Tagged t b
retag = Tagged . unTag

class ReflectNum s where reflectNum :: Num a => Tagged s a
instance                 ReflectNum  Zero     where reflectNum = Tagged 0
instance ReflectNum s => ReflectNum (Pred  s) where reflectNum = (reflectNum @ s) <&> ((-) 1) & retag
instance ReflectNum s => ReflectNum (Succ  s) where reflectNum = (reflectNum @ s) <&> ((+) 1) & retag
instance ReflectNum s => ReflectNum (Twice s) where reflectNum = (reflectNum @ s) <&> (* 2)   & retag

getReflNum :: forall s a. (ReflectNum s, Num a) => a
getReflNum = unTag (reflectNum @ s)
v3 :: Int = getReflNum  @ Zero

我们可以做得更好吗?如表达更多属性,还是以更好的方式表达?

0 个答案:

没有答案